From d22dd29b506affccc8cdc7ecfb15a57fcf330646 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Wed, 6 Sep 2023 17:03:19 +0100 Subject: [PATCH 01/41] chore: Tidy, reorganise and prepare repo docs: update changelog and documentation feat(type): Add xSmall and conform to latest figma designs. --- .github/workflows/pr.yml | 4 +- .gitignore | 5 +- CHANGELOG.md | 144 +++----- CODE_OF_CONDUCT | 58 +++ CONTRIBUTING | 27 ++ README.md | 58 ++- analysis_options.yaml | 1 - docs/components/Color/flutter.md | 102 ++++++ example/.gitignore | 44 --- example/README.md | 16 - example/ios/Podfile.lock | 13 +- example/ios/Runner.xcodeproj/project.pbxproj | 3 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- example/lib/home.dart | 73 ++++ example/lib/main.dart | 85 +---- example/lib/pages/color_example.dart | 43 ++- example/lib/pages/typography_example.dart | 8 +- example/macos/Podfile.lock | 2 +- .../macos/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- example/pubspec.lock | 88 ++--- example/test/color_test.dart | 8 +- example/test/typography_test.dart | 29 +- .../components/color_widgetbook.dart | 2 +- .../components/typography_widgetbook.dart | 1 - .../assets/fonts/IBMPlexSans-Light.otf | Bin .../assets/fonts/IBMPlexSans-Medium.otf | Bin .../assets/fonts/IBMPlexSans-Regular.otf | Bin lib/{ => src}/components/grid.dart | 10 + lib/{ => src}/components/spacing.dart | 8 + lib/{ => src}/components/text.dart | 330 +++++++----------- lib/{ => src}/theme/breakpoints.dart | 0 lib/{ => src}/theme/colors.dart | 87 +++-- lib/{ => src}/theme/colors_base.dart | 5 +- lib/{ => src}/theme/constants.dart | 0 lib/{ => src}/theme/theme.dart | 22 +- lib/{ => src}/tokens.dart | 2 +- lib/{ => src}/utils/extensions.dart | 0 lib/src/zeta.dart | 116 ++++++ lib/zeta.dart | 93 ----- lib/zeta_flutter.dart | 16 +- pubspec.yaml | 13 +- 42 files changed, 809 insertions(+), 713 deletions(-) create mode 100644 CODE_OF_CONDUCT create mode 100644 CONTRIBUTING create mode 100644 docs/components/Color/flutter.md delete mode 100644 example/.gitignore delete mode 100644 example/README.md create mode 100644 example/lib/home.dart rename lib/{ => src}/assets/fonts/IBMPlexSans-Light.otf (100%) rename lib/{ => src}/assets/fonts/IBMPlexSans-Medium.otf (100%) rename lib/{ => src}/assets/fonts/IBMPlexSans-Regular.otf (100%) rename lib/{ => src}/components/grid.dart (92%) rename lib/{ => src}/components/spacing.dart (95%) rename lib/{ => src}/components/text.dart (68%) rename lib/{ => src}/theme/breakpoints.dart (100%) rename lib/{ => src}/theme/colors.dart (91%) rename lib/{ => src}/theme/colors_base.dart (97%) rename lib/{ => src}/theme/constants.dart (100%) rename lib/{ => src}/theme/theme.dart (79%) rename lib/{ => src}/tokens.dart (99%) rename lib/{ => src}/utils/extensions.dart (100%) create mode 100644 lib/src/zeta.dart delete mode 100644 lib/zeta.dart diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index fdf9d3de..c74d4c29 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,4 +1,4 @@ -name: "PR" # TODO: Publish this as a reusable action +name: "PR" on: pull_request: @@ -49,7 +49,7 @@ jobs: uses: tj-actions/branch-names@v5.1 - uses: subosito/flutter-action@v2 with: - flutter-version: "3.10.x" + flutter-version: "3.13.x" channel: "stable" - name: Setup flutter run: flutter pub get diff --git a/.gitignore b/.gitignore index 98ad549a..f8ef7c9c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,7 @@ migrate_working_dir/ # The .vscode folder contains launch configuration and tasks you configure in # VS Code which you may wish to be included in version control, so this line # is commented out by default. -#.vscode/ +.vscode/settings.json # Flutter/Dart/Pub related # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. @@ -31,4 +31,5 @@ build/ .vscode/settings.json .flutter-plugins -.flutter-plugins-dependencies \ No newline at end of file +.flutter-plugins-dependencies +**/.fvm/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 03da4e64..71a19d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,131 +1,100 @@ -## [0.0.1+11] - 2023-08-09 -### :flying_saucer: Other Changes -- [`193dc42`](https://github.com/zebratechnologies/zeta-flutter/commit/193dc42c8e7419d9087afdffce0eae915af12819) - Feature/color ([#21](https://github.com/zebratechnologies/zeta-flutter/pull/21)) - -* feat(color): Adding color defs - -* feat(color): starting colorswatch util - -* bug(quality): updating lint rules - -* feat(color): adding widgetbook and tests - -* bug(platforms): adding windows into example - -* bug(type): Fixing reset height and tests failing *(commit by [@thelukewalton](https://github.com/thelukewalton))* +## [0.0.1+12] - 2023-09-06 +### :wrench: Chores +- [`6a2834e`](https://github.com/zebratechnologies/zeta-flutter/commit/6a2834e762c238d3927d83a239490250b1687b64) - Tidy, reorganise and prepare repo *(commit by [@thelukewalton](https://github.com/thelukewalton))* - -## [0.0.1+10] - 2023-07-11 ### :flying_saucer: Other Changes -- [`6638e94`](https://github.com/zebratechnologies/zeta-flutter/commit/6638e941b4027136c293c403c5c00e051fee5c97) - removing hardcoded shas *(PR [#19](https://github.com/zebratechnologies/zeta-flutter/pull/19) by [@thelukewalton](https://github.com/thelukewalton))* - +- [`f91e8ef`](https://github.com/zebratechnologies/zeta-flutter/commit/f91e8ef85c0a1670227d66bd441513bc33e6242c) - Feature/color ([#21](https://github.com/zebratechnologies/zeta-flutter/pull/21)) -## [0.0.1+9] - 2023-03-28 -### :memo: Documentation Changes -- [`fb835a4`](https://github.com/zebratechnologies/zeta-flutter/commit/fb835a43a94945989d5b0793d61894ea807bc745) - Updated spacing and grid documentation and edge cases *(PR [#11](https://github.com/zebratechnologies/zeta-flutter/pull/11) by [@thelukewalton](https://github.com/thelukewalton))* -- [`2a1cea3`](https://github.com/zebratechnologies/zeta-flutter/commit/2a1cea32d40c324cf36517cf05b5bb705d6eadb3) - Update typography documentation *(PR [#16](https://github.com/zebratechnologies/zeta-flutter/pull/16) by [@thelukewalton](https://github.com/thelukewalton))* -- [`79683b6`](https://github.com/zebratechnologies/zeta-flutter/commit/79683b6748e650e3bb61789e31e7ab7a7c153f88) - update docs *(PR [#17](https://github.com/zebratechnologies/zeta-flutter/pull/17) by [@thelukewalton](https://github.com/thelukewalton))* - -### :flying_saucer: Other Changes -- [`5a50e46`](https://github.com/zebratechnologies/zeta-flutter/commit/5a50e46f3500a9b186515305514839651576a444) - Update README.md ([#12](https://github.com/zebratechnologies/zeta-flutter/pull/12)) +* feat(color): Adding color defs -* Update README.md +* feat(color): starting colorswatch util -adding in tag to pass the CodeQL enablement exeption +* bug(quality): updating lint rules -* [automated commit] lint format and import sort +* feat(color): adding widgetbook and tests ---------- +* bug(platforms): adding windows into example -Co-authored-by: github-actions *(commit by [@knxp34](https://github.com/knxp34))* -- [`ffb9596`](https://github.com/zebratechnologies/zeta-flutter/commit/ffb9596ee04456147b87c2c35b3a08e8763bf7c2) - feat(typography) ([#14](https://github.com/zebratechnologies/zeta-flutter/pull/14)) - -* feat(typogrpahy): Initialising typography components - -* feat(typography): Added typography styles, text widget, widgetbook, docs, example app and tests *(commit by [@thelukewalton](https://github.com/thelukewalton))* -- [`591b757`](https://github.com/zebratechnologies/zeta-flutter/commit/591b7572ebf85da7510a8b6a3f9f8451dc93535a) - inject token to action; *(PR [#15](https://github.com/zebratechnologies/zeta-flutter/pull/15) by [@thelukewalton](https://github.com/thelukewalton))* -- [`69e6d5d`](https://github.com/zebratechnologies/zeta-flutter/commit/69e6d5da4b681293d0019d8bc143ada6478c1032) - Update README.md +* bug(type): Fixing reset height and tests failing *(commit by [@thelukewalton](https://github.com/thelukewalton))* -fixed the label *(commit by [@knxp34](https://github.com/knxp34))* -- [`1dcbcae`](https://github.com/zebratechnologies/zeta-flutter/commit/1dcbcaec2600210efcefc80861c29aaa7e44c27e) - removing hardcoded shas *(PR [#19](https://github.com/zebratechnologies/zeta-flutter/pull/19) by [@thelukewalton](https://github.com/thelukewalton))* +## 0.0.1+11 - 2023-08-09 -## [0.0.1+8] - 2023-03-27 -### :memo: Documentation Changes -- [`fb835a4`](https://github.com/zebratechnologies/zeta-flutter/commit/fb835a43a94945989d5b0793d61894ea807bc745) - Updated spacing and grid documentation and edge cases *(PR [#11](https://github.com/zebratechnologies/zeta-flutter/pull/11) by [@thelukewalton](https://github.com/thelukewalton))* -- [`2a1cea3`](https://github.com/zebratechnologies/zeta-flutter/commit/2a1cea32d40c324cf36517cf05b5bb705d6eadb3) - Update typography documentation *(PR [#16](https://github.com/zebratechnologies/zeta-flutter/pull/16) by [@thelukewalton](https://github.com/thelukewalton))* -- [`709f771`](https://github.com/zebratechnologies/zeta-flutter/commit/709f77185be705507475d90f044f94b2908fa5bb) - update docs *(PR [#17](https://github.com/zebratechnologies/zeta-flutter/pull/17) by [@thelukewalton](https://github.com/thelukewalton))* +### :sparkles: New Features -### :flying_saucer: Other Changes -- [`5a50e46`](https://github.com/zebratechnologies/zeta-flutter/commit/5a50e46f3500a9b186515305514839651576a444) - Update README.md ([#12](https://github.com/zebratechnologies/zeta-flutter/pull/12)) +- [`193dc42`](https://github.com/zebratechnologies/zeta-flutter/commit/193dc42c8e7419d9087afdffce0eae915af12819) - Color ([#21](https://github.com/zebratechnologies/zeta-flutter/pull/21)) _(commit by [@thelukewalton](https://github.com/thelukewalton))_ -* Update README.md + - [`a605819`](https://github.com/zebratechnologies/zeta-flutter/commit/a60581973764b5d06711fe6470f9963af934b7ad) - Adding color defs by [@thelukewalton](https://github.com/thelukewalton) + - [`f519cd8`](https://github.com/zebratechnologies/zeta-flutter/commit/f519cd856c7b4793ea7e24dc16f3abba0cffcf66) - starting colorswatch util by [@thelukewalton](https://github.com/thelukewalton) + - [`7445db0`](https://github.com/zebratechnologies/zeta-flutter/commit/7445db0b7da2434f5a55d3067369b3bd35df363b) - adding widgetbook and tests by [@thelukewalton](https://github.com/thelukewalton) -adding in tag to pass the CodeQL enablement exeption +### :bug: Bug Fixes -* [automated commit] lint format and import sort +- [`7529402`](https://github.com/zebratechnologies/zeta-flutter/commit/75294029f65d2a23cd41b5604165987fe434ea2e) - bug(quality): updating lint rules by [@thelukewalton](https://github.com/thelukewalton) +- [`3479adb`](https://github.com/zebratechnologies/zeta-flutter/commit/3479adb574c9ec1073552f888631f7cee12fe4cb) -bug(platforms): adding windows into example by [@thelukewalton](https://github.com/thelukewalton) +- [`70a6144`](https://github.com/zebratechnologies/zeta-flutter/commit/70a614446c4d526315eb3229478d89dbd1c031de) - bug(type): Fixing reset height and tests failing by [@thelukewalton](https://github.com/thelukewalton) ---------- +## 0.0.1+10 - 2023-07-11 -Co-authored-by: github-actions *(commit by [@knxp34](https://github.com/knxp34))* -- [`ffb9596`](https://github.com/zebratechnologies/zeta-flutter/commit/ffb9596ee04456147b87c2c35b3a08e8763bf7c2) - feat(typography) ([#14](https://github.com/zebratechnologies/zeta-flutter/pull/14)) +### :sparkles: New Features -* feat(typogrpahy): Initialising typography components +- [`546739c`](https://github.com/zebratechnologies/zeta-flutter/commit/546739c888e026b46546e22b3e1ea59c69e992d3) - Dimensions by [@thelukewalton](https://github.com/thelukewalton) -* feat(typography): Added typography styles, text widget, widgetbook, docs, example app and tests *(commit by [@thelukewalton](https://github.com/thelukewalton))* -- [`591b757`](https://github.com/zebratechnologies/zeta-flutter/commit/591b7572ebf85da7510a8b6a3f9f8451dc93535a) - inject token to action; *(PR [#15](https://github.com/zebratechnologies/zeta-flutter/pull/15) by [@thelukewalton](https://github.com/thelukewalton))* -- [`d591856`](https://github.com/zebratechnologies/zeta-flutter/commit/d59185680879bf2f938c4f2a6bd2328f29a3ddd2) - test *(commit by [@thelukewalton](https://github.com/thelukewalton))* +### :bug: Bug Fixes +- [`6638e94`](https://github.com/zebratechnologies/zeta-flutter/commit/6638e941b4027136c293c403c5c00e051fee5c97) - bug: Refactoring tokens by [@thelukewalton](https://github.com/thelukewalton) +- [`133a7ac`](https://github.com/zebratechnologies/zeta-flutter/commit/133a7acb3286af77a728479f8fafe9cef532130e) - bug: grid widgetbook hybrid example fix by [@thelukewalton](https://github.com/thelukewalton) -## [0.0.1+6] - Spacing - 2023-03-06 +- [`988964e`](https://github.com/zebratechnologies/zeta-flutter/commit/988964e122128c4f9e4423fd849b70b6283ccea7) - removing unused dependency; by [@thelukewalton](https://github.com/thelukewalton) -### :flying_saucer: Other Changes +## 0.0.1+9 - 2023-03-28 -- [`e29e53b`](https://github.com/zebratechnologies/zeta-flutter/commit/e29e53ba132cd155f2d40f4cfa6f6c3060558b4e) - fix(actions) another attempt at fixing actions checkout _(PR [#8](https://github.com/zebratechnologies/zeta-flutter/pull/8) by [@thelukewalton](https://github.com/thelukewalton))_ -- [`1dc0e1b`](https://github.com/zebratechnologies/zeta-flutter/commit/1dc0e1b64cb870685110516c5159b20fb903f2c3) - Update README.md _(commit by [@benken](https://github.com/benken))_ -- [`a2ca78e`](https://github.com/zebratechnologies/zeta-flutter/commit/a2ca78e863405f70b8199a889be3bc4f9c61ab1a) - Feature/spacing ([#9](https://github.com/zebratechnologies/zeta-flutter/pull/9)) +### :sparkles: New Features -* added spacing widget +- [`ffb9596`](https://github.com/zebratechnologies/zeta-flutter/commit/ffb9596ee04456147b87c2c35b3a08e8763bf7c2) - Typography _(commit by [@thelukewalton](https://github.com/thelukewalton))_ -* feature(Spacing): Added documentation and tests +### :memo: Documentation Changes -* bug: Updating left / right to start end. Potentially left / right could be added back. For now using start / end only _(commit by [@thelukewalton](https://github.com/thelukewalton))_ +- [`fb835a4`](https://github.com/zebratechnologies/zeta-flutter/commit/fb835a43a94945989d5b0793d61894ea807bc745) - Updated spacing and grid documentation and edge cases _(PR [#11](https://github.com/zebratechnologies/zeta-flutter/pull/11) by [@thelukewalton](https://github.com/thelukewalton))_ +- [`2a1cea3`](https://github.com/zebratechnologies/zeta-flutter/commit/2a1cea32d40c324cf36517cf05b5bb705d6eadb3) - Update typography documentation _(PR [#16](https://github.com/zebratechnologies/zeta-flutter/pull/16) by [@thelukewalton](https://github.com/thelukewalton))_ +- [`709f771`](https://github.com/zebratechnologies/zeta-flutter/commit/709f77185be705507475d90f044f94b2908fa5bb) - update docs _(PR [#17](https://github.com/zebratechnologies/zeta-flutter/pull/17) by [@thelukewalton](https://github.com/thelukewalton))_ -## [0.0.1+5] - Grid - 2023-02-17 +- [`5a50e46`](https://github.com/zebratechnologies/zeta-flutter/commit/5a50e46f3500a9b186515305514839651576a444) - Update README.md ([#12](https://github.com/zebratechnologies/zeta-flutter/pull/12)), Update README.md, adding in tag to pass the CodeQL enablement exeption, - [automated commit] lint format and import sort. Co-authored-by: github-actions _(commit by [@knxp34](https://github.com/knxp34))_ ### :bug: Bug Fixes -- [`f7a8d9a`](https://github.com/zebratechnologies/zeta-flutter/commit/f7a8d9a2ba078bf08fe80de07f6e9c871af9e451) - **actions**: Updated actions to push changelog to zeta. _(PR [#6](https://github.com/zebratechnologies/zeta-flutter/pull/6) by [@thelukewalton](https://github.com/thelukewalton))_ +- [`591b757`](https://github.com/zebratechnologies/zeta-flutter/commit/591b7572ebf85da7510a8b6a3f9f8451dc93535a) - inject token to action; _(PR [#15](https://github.com/zebratechnologies/zeta-flutter/pull/15) by [@thelukewalton](https://github.com/thelukewalton))_ +- [`d591856`](https://github.com/zebratechnologies/zeta-flutter/commit/d59185680879bf2f938c4f2a6bd2328f29a3ddd2) - test _(commit by [@thelukewalton](https://github.com/thelukewalton))_ +- [`1dcbcae`](https://github.com/zebratechnologies/zeta-flutter/commit/1dcbcaec2600210efcefc80861c29aaa7e44c27e) - removing hardcoded shas _(PR [#19](https://github.com/zebratechnologies/zeta-flutter/pull/19) by [@thelukewalton](https://github.com/thelukewalton))_ -### :flying_saucer: Other Changes - -- [`60527e8`](https://github.com/zebratechnologies/zeta-flutter/commit/60527e86da15b4a804990c7e67bae5c46d25dc7f) - Feature/grid ([#1](https://github.com/zebratechnologies/zeta-flutter/pull/1)) +## 0.0.1+6 - Spacing - 2023-03-06 -* setup grid +### :sparkles: New Features -* symmetrical grid using rows +- [`a2ca78e`](https://github.com/zebratechnologies/zeta-flutter/commit/a2ca78e863405f70b8199a889be3bc4f9c61ab1a) - Spacing ([#9](https://github.com/zebratechnologies/zeta-flutter/pull/9)) + _(commit by [@thelukewalton](https://github.com/thelukewalton))_ -* Asymmetrical +### :bug: Bug Fixes -* documentation +- [`e29e53b`](https://github.com/zebratechnologies/zeta-flutter/commit/e29e53ba132cd155f2d40f4cfa6f6c3060558b4e) - another attempt at fixing actions checkout _(PR [#8](https://github.com/zebratechnologies/zeta-flutter/pull/8) by [@thelukewalton](https://github.com/thelukewalton))_ -* widgetbook +### :memo: Documentation Changes -* Hyrbid +- [`1dc0e1b`](https://github.com/zebratechnologies/zeta-flutter/commit/1dc0e1b64cb870685110516c5159b20fb903f2c3) - Update README.md _(commit by [@benken](https://github.com/benken))_ -* actions _(commit by [@thelukewalton](https://github.com/thelukewalton))_ +## 0.0.1+5 - Grid - 2023-02-17 -- [`0340212`](https://github.com/zebratechnologies/zeta-flutter/commit/0340212963606fbe755aa94cbb98d38d663a5854) - fixing action ([#4](https://github.com/zebratechnologies/zeta-flutter/pull/4)) +### :sparkles: New Features -* fixing action +- [`60527e8`](https://github.com/zebratechnologies/zeta-flutter/commit/60527e86da15b4a804990c7e67bae5c46d25dc7f) - Grid ([#1](https://github.com/zebratechnologies/zeta-flutter/pull/1)) -* [automated commit] lint format and import sort +### :bug: Bug Fixes -Co-authored-by: github-actions _(commit by [@thelukewalton](https://github.com/thelukewalton))_ +- [`f7a8d9a`](https://github.com/zebratechnologies/zeta-flutter/commit/f7a8d9a2ba078bf08fe80de07f6e9c871af9e451) - **actions**: Updated actions to push changelog to zeta. _(PR [#6](https://github.com/zebratechnologies/zeta-flutter/pull/6) by [@thelukewalton](https://github.com/thelukewalton))_ - actions _(commit by [@thelukewalton](https://github.com/thelukewalton))_ -- [`b0ad7f1`](https://github.com/zebratechnologies/zeta-flutter/commit/b0ad7f12b8b583fb928d225ce9d1c1f3244046e5) - No ticket/code examples ([#5](https://github.com/zebratechnologies/zeta-flutter/pull/5)) +- [`0340212`](https://github.com/zebratechnologies/zeta-flutter/commit/0340212963606fbe755aa94cbb98d38d663a5854) - fixing action ([#4](https://github.com/zebratechnologies/zeta-flutter/pull/4)) -adding code example _(commit by [@thelukewalton](https://github.com/thelukewalton))_ +- [`b0ad7f1`](https://github.com/zebratechnologies/zeta-flutter/commit/b0ad7f12b8b583fb928d225ce9d1c1f3244046e5) - No ticket/code examples ([#5](https://github.com/zebratechnologies/zeta-flutter/pull/5))- adding code example _(commit by [@thelukewalton](https://github.com/thelukewalton))_ - [`4acf3c1`](https://github.com/zebratechnologies/zeta-flutter/commit/4acf3c1134b6c8d17827d8e2c665250d6f6ead1d) - fix(actions) Fix action refs _(PR [#7](https://github.com/zebratechnologies/zeta-flutter/pull/7) by [@thelukewalton](https://github.com/thelukewalton))_ - [`83e073b`](https://github.com/zebratechnologies/zeta-flutter/commit/83e073b16808d89373a74dba35172bb7a978e765) - fix(actions) another attempt at fixing actions checkout _(PR [#8](https://github.com/zebratechnologies/zeta-flutter/pull/8) by [@thelukewalton](https://github.com/thelukewalton))_ @@ -134,9 +103,4 @@ adding code example _(commit by [@thelukewalton](https://github.com/thelukewalto - Initial setup -[0.0.1+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+1...0.0.1+5 - -[0.0.1+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+6...0.0.1+8 -[0.0.1+9]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+6...0.0.1+9 -[0.0.1+10]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+9...0.0.1+10 -[0.0.1+11]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+10...0.0.1+11 \ No newline at end of file +[0.0.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+11...0.0.1+12 \ No newline at end of file diff --git a/CODE_OF_CONDUCT b/CODE_OF_CONDUCT new file mode 100644 index 00000000..fd77c7dc --- /dev/null +++ b/CODE_OF_CONDUCT @@ -0,0 +1,58 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. +Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +Devrel@zebra.com. +All complaints will be reviewed and investigated promptly and fairly. +The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the Contributor Covenant, +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 00000000..2ccbf54b --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,27 @@ +# Getting Involved + +Thank you for your interest in this project. We'd love to see your contributions. There are just few small guidelines you need to follow. +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Opening an issue + +If you've noticed a bug or you have a suggestion for a new feature, please go ahead and open an issue in this project. Please do include as much information as possible. + +Please file issues before doing substantial work; this will ensure that others don't duplicate the work and that there's a chance to discuss any design issues. + +## Making a code change + +We're always open to pull requests, but these should be small and clearly described so that we can understand what you're trying to do. + +When you're ready to start coding, fork the needed repository to your own GitHub account and make your changes in a new branch. Once you're happy, open a pull request and explain what the change is and why you think we should include it in our project. + +## Code reviews + +All submissions, including submissions by project members, require review. We use GitHub pull requests (PRs) for this purpose. Consult [GitHub Help](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests) for more information on using pull requests. + +Before a PR can be reviewed, ensure you have done the following, and fixed any issues that may arise: + +- Ensure branch is up to date `git rebase main` +- Check formatting: `flutter format .` +- Run static analyses: `flutter analyze` +- Run unit-tests: `flutter test` diff --git a/README.md b/README.md index 12f8ea07..284d1448 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,43 @@ -
- Zebra Repository Information -
    -
  • Zebra Business Unit : DMO - Innovation & Design
  • -
  • Zebra Manager : ncvt73
  • -
  • Zebra Repo Admin: lwalton
  • -
  • Zebra Jira Project ID: N/A
  • -
  • Product: Zebra Design System (Zeta) - Flutter Component Library
  • -
  • Topics: no_codeql
  • -
-
- -# zeta-flutter - -Zebra Design System (Zeta) - Flutter Component Library +# Zeta Flutter + +Zeta is the new, formal, standardized Zebra Design System based off the successes of ZDS (Zebra Design System). + +Note: This package is in pre-release, and so many aspects are incomplete. + +# Usage + +[Install zeta_flutter](https://pub.dev/packages/zeta_flutter/install) + +Zeta extends the use of Flutter's built in theming tools, and so to work correctly your app needs to be wrapped with the zeta theme as such: + +```dart + + @override + Widget build(BuildContext context) { + return Zeta( + builder: (context, theme, colors) { + return MaterialApp.router(theme: theme, routerConfig: router); + }, + ); + } +``` + +This returns the Zeta theme and colors, which will be used across the app. Custom `ThemeData` and `ZetaColor` objects can be passed in to apply custom themes and colors. + +## Viewing the components + +To view examples of all the components in the library, you can run the example app in this repo or go to [Zeta](https://zeta-ds.web.app/) + +## Licensing + +This software is licensed with the MIT license (see [LICENSE](./LICENSE)). + +--- + +### Pre release TODOs + +[ ] TODO: update actions + +[ ] TODO: Make public repo + +[ ] TODO: Add to pub.dev diff --git a/analysis_options.yaml b/analysis_options.yaml index dd2905be..b689dcb6 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -30,7 +30,6 @@ linter: avoid_types_on_closure_parameters: false cascade_invocations: false close_sinks: false - diagnostic_describe_all_properties: false lines_longer_than_80_chars: false omit_local_variable_types: false prefer_constructors_over_static_methods: false diff --git a/docs/components/Color/flutter.md b/docs/components/Color/flutter.md new file mode 100644 index 00000000..86eec97e --- /dev/null +++ b/docs/components/Color/flutter.md @@ -0,0 +1,102 @@ +## ZetaColors Usage + +To import ZetaColors into a Dart file: + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; +``` + +### Example + +ZetaColors should be an app-wide parameter, to ensure colors throughout an app stay consistent. As such, it should be created at the highest level of an app, from where it can be distributed. + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; + +class MyApp extends StatelessWidget{ + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + + /// Build colors object with custom colors. + final ZetaColors colors = ZetaColors( + /// Add custom colors here. + ); + + /// Wrap whole app with [Zeta] to provide theming. + return Zeta( + colors: colors, + builder: (BuildContext context, ThemeData theme, ZetaColors colors) => ZetaColorExample(), + ); + } +} + +class ZetaColorExample extends StatelessWidget{ + const ZetaColorExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + + + final ZetaColors colors = ZetaColors.of(context); + + return Container( + color: colors.red, + ); + } +} + +``` + +### ZetaColors + +ZetaColors provides a full range of colors to be used, with various modifiers to return colors based on function. + +The following colors are provided as `ZetaColorSwatch`: + +- primary +- secondary +- cool (grey) +- warm (grey) +- blue +- red +- green +- orange +- purple +- yellow +- teal +- pink + +When creating a custom ZetaColors object, colors should be provided as a full `ZetaColorSwatch`, unless you want to use the default values, which are described in `ZetaColorBase`. + +ZetaColors has the following modifiers: + +- primary, onPrimary +- secondary, onSecondary +- positive, onPositive, negative, onNegative, warning, onWarning, info, onInfo +- surface, onSurface, surfaceDisabled, surfaceHovered, surfaceSecondary, surfaceTertiary, surfaceSelectedHovered, surfaceSelected +- background, onBackground +- textDefault, textSubtle, textDisabled, textInverse, +- borderDefault, borderSubtle, borderDisabled, borderSelected, +- white, black +- link, linkVisited, +- textLightMode, textDarkMode + +Commonly, `ZetaColors.toColorScheme` should be used to create a color scheme for use with `MaterialApp`. + +### ZetaColorSwatch + +ZetaColorSwatch returns a swatch of colors with shades at 10, 20, 30, 40, 50, 60, 70, 80, 90 and 100 where the higher the value, the darker the color. + +ZetaColorSwatch has the following modifiers: + +- primary +- icon +- border, borderSubtle +- surface +- subtle +- on +- disabled + +ZetaColorSwatch can be generated from a single color, but this is not recommended as results may not look as expected, and will probably not conform to any accessability requirements. diff --git a/example/.gitignore b/example/.gitignore deleted file mode 100644 index 24476c5d..00000000 --- a/example/.gitignore +++ /dev/null @@ -1,44 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -/build/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/example/README.md b/example/README.md deleted file mode 100644 index 7e10926e..00000000 --- a/example/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# zeta_example - -Demonstrates how to use the zeta plugin. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index ccaa3cc1..d403d6cb 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,22 +1,23 @@ PODS: - Flutter (1.0.0) - - zeta (0.0.1): + - path_provider_foundation (0.0.1): - Flutter + - FlutterMacOS DEPENDENCIES: - Flutter (from `Flutter`) - - zeta (from `.symlinks/plugins/zeta/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) EXTERNAL SOURCES: Flutter: :path: Flutter - zeta: - :path: ".symlinks/plugins/zeta/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" SPEC CHECKSUMS: Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - zeta: d56cf33a2716f24c37bd8e71ab754f8b79e9d602 + path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.11.3 +COCOAPODS: 1.12.1 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 1950e945..83853dd6 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -156,7 +156,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -227,6 +227,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a3..a6b826db 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ children; + Component(this.name, this.page, [this.children = const []]); +} + +final List components = [ + Component(GridExample.name, const GridExample()), + Component(SpacingExample.name, const SpacingExample()), + Component(TypographyExample.name, const TypographyExample()), + Component(ColorExample.name, const ColorExample()), +]; + +class Home extends StatefulWidget { + const Home({super.key}); + + @override + State createState() => _HomeState(); +} + +final GoRouter router = GoRouter( + routes: [ + GoRoute( + path: '/', + builder: (_, __) => const Home(), + routes: [ + ...components.map( + (e) => GoRoute( + path: e.name, + builder: (_, __) => e.page, + routes: e.children.map((f) => GoRoute(path: f.name, builder: (_, __) => f.page)).toList(), + ), + ) + ], + ), + ], +); + +class _HomeState extends State { + @override + Widget build(BuildContext context) { + final items = components..sort((a, b) => a.name.compareTo(b.name)); + + final colors = ZetaColors.of(context); + return Scaffold( + appBar: AppBar( + title: const Text('Zeta'), + backgroundColor: colors.primary, + ), + body: ColoredBox( + color: colors.background, + child: ListView.builder( + itemCount: items.length, + itemBuilder: (context, index) { + return ListTile( + title: ZetaText(items[index].name), + onTap: () => context.go('/${items[index].name}'), + ); + }, + ), + ), + ); + } +} diff --git a/example/lib/main.dart b/example/lib/main.dart index 9b854b9e..b742e1db 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,54 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import 'pages/color_example.dart'; -import 'pages/grid_example.dart'; -import 'pages/spacing_example.dart'; -import 'pages/typography_example.dart'; +import 'home.dart'; -void main() { - runApp(const MyApp()); -} - -class MyApp extends StatefulWidget { - const MyApp({super.key}); - - @override - State createState() => _MyAppState(); -} +void main() => runApp(const ZetaExample()); -class Component { - final String name; - final Widget page; - final List children; - Component(this.name, this.page, [this.children = const []]); -} - -final List components = [ - Component(GridExample.name, const GridExample()), - Component(SpacingExample.name, const SpacingExample()), - Component(TypographyExample.name, const TypographyExample()), - Component(ColorExample.name, const ColorExample()), -]; - -class _MyAppState extends State { - final GoRouter router = GoRouter( - routes: [ - GoRoute( - path: '/', - builder: (_, __) => const Home(), - routes: [ - ...components.map( - (e) => GoRoute( - path: e.name, - builder: (_, __) => e.page, - routes: e.children.map((f) => GoRoute(path: f.name, builder: (_, __) => f.page)).toList(), - ), - ) - ], - ), - ], - ); +class ZetaExample extends StatelessWidget { + const ZetaExample({super.key}); @override Widget build(BuildContext context) { @@ -59,37 +16,3 @@ class _MyAppState extends State { ); } } - -class Home extends StatefulWidget { - const Home({super.key}); - - @override - State createState() => _HomeState(); -} - -class _HomeState extends State { - @override - Widget build(BuildContext context) { - final items = components..sort((a, b) => a.name.compareTo(b.name)); - - final colors = ZetaColors.of(context); - return Scaffold( - appBar: AppBar( - title: const Text('Zeta'), - backgroundColor: colors.primary, - ), - body: ColoredBox( - color: colors.background, - child: ListView.builder( - itemCount: items.length, - itemBuilder: (context, index) { - return ListTile( - title: ZetaText(items[index].name), - onTap: () => context.go('/${items[index].name}'), - ); - }, - ), - ), - ); - } -} diff --git a/example/lib/pages/color_example.dart b/example/lib/pages/color_example.dart index bc576d1c..633b2519 100644 --- a/example/lib/pages/color_example.dart +++ b/example/lib/pages/color_example.dart @@ -102,7 +102,7 @@ class _ColorExampleState extends State { return ExampleScaffold( name: ColorExample.name, actions: [ - const Center(child: ZetaText('DarkMode', textColor: Colors.white)), + Center(child: ZetaText('DarkMode', textColor: Colors.white)), Switch.adaptive( value: colors.isDarkMode, onChanged: (isDarkMode) => ZetaColors.setColors(context, colors.copyWith(isDarkMode: isDarkMode)), @@ -123,7 +123,7 @@ class _ColorExampleState extends State { MyRow(children: backdrop, title: 'Backdrop colors'), MyRow(children: primaries, title: 'Primary colors'), MyRow(children: alerts, title: 'Alert colors'), - const Row(children: [ZetaText.displayMedium('Full color swatches')]).squish(Dimensions.x8), + Row(children: [ZetaText.displayMedium('Full color swatches')]).squish(Dimensions.x8), ...swatches.entries.map( (value) => Row( children: List.generate(10, (index) => 100 - (10 * index)) @@ -161,36 +161,41 @@ class _ColorExampleState extends State { child: const Text('Toggle generated colors').square(Dimensions.s), ).square(Dimensions.s), if (showGeneratedColors) - const Row(children: [ZetaText.displayMedium('Generated color swatches')]).squish(Dimensions.x8), + Row(children: [ZetaText.displayMedium('Generated color swatches')]).squish(Dimensions.x8), if (showGeneratedColors) ...generatedSwatches.entries.map( (value) => Row( - children: List.generate(10, (index) => 100 - (10 * index)) + children: List.generate(11, (index) => 110 - (10 * index)) .map( (e) => Expanded( child: Container( height: constraints.maxWidth / 10, - color: value.value[e], - child: FittedBox( - fit: BoxFit.scaleDown, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - DefaultTextStyle( - style: ZetaText.zetaBodyMedium - .copyWith(color: calculateTextColor(value.value[e] ?? Colors.white)), + color: e == 110 ? colors.surface : value.value[e], + child: e == 110 + ? SizedBox() + : FittedBox( + fit: BoxFit.scaleDown, child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Text('${value.key.toLowerCase().replaceAll(' ', '')}-$e'), - Text( - value.value[e].toString().replaceAll('Color(0xff', '#').substring(0, 7), + DefaultTextStyle( + style: ZetaText.zetaBodyMedium + .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), + ), + ], + ), ), ], ), ), - ], - ), - ), ), ), ) diff --git a/example/lib/pages/typography_example.dart b/example/lib/pages/typography_example.dart index 1387457e..8be0e9b0 100644 --- a/example/lib/pages/typography_example.dart +++ b/example/lib/pages/typography_example.dart @@ -37,7 +37,7 @@ class TypographyExample extends StatelessWidget { }, ).toList(); - static const dedicatedSizes = [ + static final dedicatedSizes = [ ExampleModel( example: ZetaText.bodySmall(exampleText), wDescription: ZetaText.bodySmall(exampleParagraph, maxWidth: 66), @@ -170,13 +170,13 @@ class TypographyExample extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const ZetaText.headingLarge('Text').inline(Dimensions.x10), + ZetaText.headingLarge('Text').inline(Dimensions.x10), ...tokens.map(ExampleBuilder.new), const Divider().squish(Dimensions.x4), - const ZetaText.headingLarge('Universal sizes').inline(Dimensions.x10), + ZetaText.headingLarge('Universal sizes').inline(Dimensions.x10), ...universalSizes.map(ExampleBuilder.new), const Divider().squish(Dimensions.x4), - const ZetaText.headingLarge('Dedicated sizes').inline(Dimensions.x10), + ZetaText.headingLarge('Dedicated sizes').inline(Dimensions.x10), ...dedicatedSizes.map(ExampleBuilder.new), ], ), diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index 92122f48..f632ebd4 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -16,7 +16,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 + path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index 60f1329d..d644e73f 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -203,7 +203,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index fb7259e1..83d88728 100644 --- a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ =3.0.1 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.7.0" diff --git a/example/test/color_test.dart b/example/test/color_test.dart index 6b4562e3..fb5009a5 100644 --- a/example/test/color_test.dart +++ b/example/test/color_test.dart @@ -3,8 +3,8 @@ import 'package:zeta_flutter/zeta_flutter.dart'; void main() { testWidgets('Dark mode value', (tester) async { - const ZetaColors light = ZetaColors(); - const ZetaColors dark = ZetaColors(isDarkMode: true); + final ZetaColors light = ZetaColors(); + final ZetaColors dark = ZetaColors(isDarkMode: true); expect(light.primary.shade10, dark.primary.shade100); expect(light.primary.shade20, dark.primary.shade90); @@ -14,8 +14,8 @@ void main() { }); testWidgets('AAA mode value', (tester) async { - const ZetaColors aa = ZetaColors(); - const ZetaColors aaa = ZetaColors(isAAA: true); + final ZetaColors aa = ZetaColors(); + final ZetaColors aaa = ZetaColors(isAAA: true); expect(aa.primary.primary, aa.primary.shade60); expect(aaa.primary.primary, aaa.primary.shade80); diff --git a/example/test/typography_test.dart b/example/test/typography_test.dart index c22ec2ca..c33abdf0 100644 --- a/example/test/typography_test.dart +++ b/example/test/typography_test.dart @@ -33,8 +33,8 @@ void main() { first: true, last: true, ), - const ZetaText(exampleText, style: ZetaText.zetaHeadingLarge, key: key3), - const ZetaText.headingLarge(exampleText, key: key4), + ZetaText(exampleText, style: ZetaText.zetaHeadingLarge, key: key3), + ZetaText.headingLarge(exampleText, key: key4), ], ); }, @@ -98,29 +98,4 @@ void main() { expect(padding2.padding, EdgeInsets.zero); expect(text3, text4); }); - - testWidgets('Responsive', (tester) async { - await tester.pumpWidget( - const TestWidget( - screenSize: Size(200, 400), - widget: Column(children: [ZetaText.displayLarge(exampleText, key: key1)]), - ), - ); - - final Finder zetaText1 = find.byKey(key1); - final InlineSpan text1 = - (find.descendant(of: zetaText1, matching: find.byType(RichText)).evaluate().first.widget as RichText).text; - - expect( - TextStyle( - fontSize: text1.style?.fontSize, - height: text1.style?.height, - fontWeight: text1.style?.fontWeight, - ), - ZetaText.zetaDisplayLargeResponsive, - ); - - expect(text1.style?.fontFamily, 'packages/zeta_flutter/IBMPlexSans'); - expect(text1.style?.color, const Color(0xFF1D1E23)); - }); } diff --git a/example/widgetbook/components/color_widgetbook.dart b/example/widgetbook/components/color_widgetbook.dart index e2a2c2f4..1c70872a 100644 --- a/example/widgetbook/components/color_widgetbook.dart +++ b/example/widgetbook/components/color_widgetbook.dart @@ -99,7 +99,7 @@ WidgetbookComponent colorWidgetBook() { MyRow(children: backdrop, title: 'Backdrop colors'), MyRow(children: primaries, title: 'Primary colors'), MyRow(children: alerts, title: 'Alert colors'), - const Row(children: [ZetaText.displayMedium('Full color swatches')]).squish(Dimensions.x8), + Row(children: [ZetaText.displayMedium('Full color swatches')]).squish(Dimensions.x8), ...swatches.entries.map( (value) { return Row( diff --git a/example/widgetbook/components/typography_widgetbook.dart b/example/widgetbook/components/typography_widgetbook.dart index d7f6d879..0d638ff6 100644 --- a/example/widgetbook/components/typography_widgetbook.dart +++ b/example/widgetbook/components/typography_widgetbook.dart @@ -8,7 +8,6 @@ WidgetbookComponent textWidgetBook() { 'Body small': ZetaText.zetaBodySmall, 'Body medium': ZetaText.zetaBodyMedium, 'Body large': ZetaText.zetaBodyLarge, - 'Description': ZetaText.zetaDescription, 'Headline small': ZetaText.zetaHeadingSmall, 'Headline medium': ZetaText.zetaHeadingMedium, 'Headline large': ZetaText.zetaHeadingLarge, diff --git a/lib/assets/fonts/IBMPlexSans-Light.otf b/lib/src/assets/fonts/IBMPlexSans-Light.otf similarity index 100% rename from lib/assets/fonts/IBMPlexSans-Light.otf rename to lib/src/assets/fonts/IBMPlexSans-Light.otf diff --git a/lib/assets/fonts/IBMPlexSans-Medium.otf b/lib/src/assets/fonts/IBMPlexSans-Medium.otf similarity index 100% rename from lib/assets/fonts/IBMPlexSans-Medium.otf rename to lib/src/assets/fonts/IBMPlexSans-Medium.otf diff --git a/lib/assets/fonts/IBMPlexSans-Regular.otf b/lib/src/assets/fonts/IBMPlexSans-Regular.otf similarity index 100% rename from lib/assets/fonts/IBMPlexSans-Regular.otf rename to lib/src/assets/fonts/IBMPlexSans-Regular.otf diff --git a/lib/components/grid.dart b/lib/src/components/grid.dart similarity index 92% rename from lib/components/grid.dart rename to lib/src/components/grid.dart index 0da36dd8..ddac4c9f 100644 --- a/lib/components/grid.dart +++ b/lib/src/components/grid.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../theme/breakpoints.dart'; @@ -142,4 +143,13 @@ class ZetaGrid extends StatelessWidget { }, ); } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('hybrid', hybrid)); + properties.add(DoubleProperty('col', col)); + properties.add(DiagnosticsProperty('noGaps', noGaps)); + properties.add(IntProperty('asymmetricWeight', asymmetricWeight)); + } } diff --git a/lib/components/spacing.dart b/lib/src/components/spacing.dart similarity index 95% rename from lib/components/spacing.dart rename to lib/src/components/spacing.dart index 99daf6e9..9762c6fc 100644 --- a/lib/components/spacing.dart +++ b/lib/src/components/spacing.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import '../tokens.dart'; @@ -132,6 +133,13 @@ class ZetaSpacing extends StatelessWidget { return child.inlineEnd(size); } } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(EnumProperty('type', type)); + properties.add(DoubleProperty('size', size)); + } } /// Extension to get Spacing type as [EdgeInsets] from a double. diff --git a/lib/components/text.dart b/lib/src/components/text.dart similarity index 68% rename from lib/components/text.dart rename to lib/src/components/text.dart index df1d1031..9b49f99f 100644 --- a/lib/components/text.dart +++ b/lib/src/components/text.dart @@ -1,35 +1,8 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../theme/theme.dart'; +import '../../zeta_flutter.dart'; import '../tokens.dart' as tokens; -import 'spacing.dart'; - -/// Determine whether to show mobile text for heading / display. -extension ResponsiveBreak on DeviceType { - /// Determine whether to show mobile text for heading / display. - bool get responsiveText { - return name == 'mobileLandscape' || name == 'mobilePortrait'; - } -} - -/// Extension to add [mobileStyle] to [TextStyle]. -extension Responsive on TextStyle { - /// Gets a responsive variant of a Zeta TextStyle. - /// - /// Variants exist for Zeta Heading and Display TextStyles, otherwise the TextStyle is returned unchanged. - TextStyle get mobileStyle { - final Map responsiveMap = { - ZetaText.zetaHeadingSmall: ZetaText.zetaHeadingSmallResponsive, - ZetaText.zetaHeadingMedium: ZetaText.zetaHeadingMediumResponsive, - ZetaText.zetaHeadingLarge: ZetaText.zetaHeadingLargeResponsive, - ZetaText.zetaDisplaySmall: ZetaText.zetaDisplaySmallResponsive, - ZetaText.zetaDisplayMedium: ZetaText.zetaDisplayMediumResponsive, - ZetaText.zetaDisplayLarge: ZetaText.zetaDisplayLargeResponsive, - }; - - return responsiveMap[this] ?? this; - } -} /// {@template zeta-component-text} /// ZetaText component. @@ -45,7 +18,7 @@ class ZetaText extends StatelessWidget { /// Text styles for Zeta. /// /// {@macro zeta-theme} - static const TextTheme textTheme = TextTheme( + static TextTheme textTheme = TextTheme( displayLarge: zetaDisplayLarge, displayMedium: zetaDisplayMedium, displaySmall: zetaDisplaySmall, @@ -63,7 +36,7 @@ class ZetaText extends StatelessWidget { labelSmall: zetaLabelSmall, ); - /// Buids text theme for app based on an instance of [ZetaColors]. + /// Builds text theme for app based on an instance of [ZetaColors]. static TextTheme textThemeBuilder(ZetaColors colors) { return TextTheme( displayLarge: zetaDisplayLarge.copyWith(color: colors.textDefault), @@ -84,41 +57,30 @@ class ZetaText extends StatelessWidget { ); } - /// Returns responsive text style. + /// {@template zeta-type-body-xs} + /// Smallest body text. /// - /// Should only be used on [DeviceType.mobileLandscape] and [DeviceType.mobilePortrait]. + /// Used for UI components and UI content design. /// - /// Automatically applied in [ZetaText] but must be applied manually otherwise. - static const TextTheme textThemeMobile = TextTheme( - displayLarge: zetaDisplayLargeResponsive, - displayMedium: zetaDisplayMediumResponsive, - displaySmall: zetaDisplaySmallResponsive, - headlineLarge: zetaHeadingLargeResponsive, - headlineMedium: zetaHeadingMediumResponsive, - headlineSmall: zetaHeadingSmallResponsive, - titleLarge: zetaTitleLarge, - titleMedium: zetaTitleMedium, - titleSmall: zetaTitleSmall, - bodyLarge: zetaBodyLarge, - bodyMedium: zetaBodyMedium, - bodySmall: zetaBodySmall, - labelLarge: zetaLabelLarge, - labelMedium: zetaLabelMedium, - labelSmall: zetaLabelSmall, + /// {@endtemplate} + static TextStyle zetaBodyXSmall = const TextStyle( + fontSize: tokens.Dimensions.x3, + fontWeight: FontWeight.w400, + height: tokens.Dimensions.x3 / tokens.Dimensions.x4, ); /// {@template zeta-type-body-s} - /// Smallest body text. + /// Small body text. /// /// Used for UI components and UI content design. /// /// See also: /// * [TextTheme.bodySmall]. /// {@endtemplate} - static const TextStyle zetaBodySmall = TextStyle( - fontSize: tokens.Dimensions.x3, + static TextStyle zetaBodySmall = const TextStyle( + fontSize: tokens.Dimensions.x3_5, fontWeight: FontWeight.w400, - height: tokens.Dimensions.x4 / tokens.Dimensions.x3, + height: 18 / 14, ); /// {@template zeta-type-body-m} @@ -129,7 +91,7 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.bodyMedium]. /// {@endtemplate} - static const TextStyle zetaBodyMedium = TextStyle( + static TextStyle zetaBodyMedium = const TextStyle( fontSize: tokens.Dimensions.x4, fontWeight: FontWeight.w400, height: tokens.Dimensions.x6 / tokens.Dimensions.x4, @@ -143,10 +105,10 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.bodyLarge]. /// {@endtemplate} - static const TextStyle zetaBodyLarge = TextStyle( + static TextStyle zetaBodyLarge = const TextStyle( fontSize: tokens.Dimensions.x5, fontWeight: FontWeight.w400, - height: tokens.Dimensions.x7 / tokens.Dimensions.x5, + height: tokens.Dimensions.x6 / tokens.Dimensions.x5, ); /// {@template zeta-type-label-s} @@ -157,10 +119,10 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.labelSmall]. /// {@endtemplate} - static const TextStyle zetaLabelSmall = TextStyle( + static TextStyle zetaLabelSmall = const TextStyle( fontSize: tokens.Dimensions.x3, fontWeight: FontWeight.w500, - height: 1, + height: tokens.Dimensions.x4 / tokens.Dimensions.x3, ); /// {@template zeta-type-label-m} @@ -171,10 +133,10 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.labelMedium]. /// {@endtemplate} - static const TextStyle zetaLabelMedium = TextStyle( - fontSize: tokens.Dimensions.x4, + static TextStyle zetaLabelMedium = const TextStyle( + fontSize: tokens.Dimensions.x3_5, fontWeight: FontWeight.w500, - height: 1, + height: tokens.Dimensions.x3_5 / tokens.Dimensions.x5, ); /// {@template zeta-type-label-l} @@ -185,52 +147,56 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.labelLarge]. /// {@endtemplate} - static const TextStyle zetaLabelLarge = TextStyle( - fontSize: tokens.Dimensions.x5, + static TextStyle zetaLabelLarge = const TextStyle( + fontSize: tokens.Dimensions.x4, fontWeight: FontWeight.w500, - height: 1, + height: tokens.Dimensions.x4 / tokens.Dimensions.x6, ); /// {@template zeta-type-title-s} - /// Small title text. + /// Heading 6 / Small title text. /// /// Used for UI components and UI content design. /// /// See also: /// * [TextTheme.titleSmall]. /// {@endtemplate} - static const TextStyle zetaTitleSmall = TextStyle( + static TextStyle zetaTitleSmall = const TextStyle( fontSize: tokens.Dimensions.x3, fontWeight: FontWeight.w500, height: tokens.Dimensions.x4 / tokens.Dimensions.x3, ); /// {@template zeta-type-title-m} - /// Medium title text. + /// Heading 5 / Medium title text. /// /// Used for UI components and UI content design. /// /// See also: /// * [TextTheme.titleMedium]. /// {@endtemplate} - static const TextStyle zetaTitleMedium = TextStyle( + static TextStyle zetaTitleMedium = const TextStyle( fontSize: tokens.Dimensions.x4, fontWeight: FontWeight.w500, height: tokens.Dimensions.x5 / tokens.Dimensions.x4, ); +// TODO(tokens): How to add color and font family here? +// Both can be changed at runtime so can;t be const. +// But also how do we access them without state? + /// {@template zeta-type-title-l} - /// Large title text. + /// Heading 4 / Large title text. /// /// Used for UI sections and landing pages. /// /// See also: /// * [TextTheme.titleLarge]. /// {@endtemplate} - static const TextStyle zetaTitleLarge = TextStyle( + static TextStyle zetaTitleLarge = const TextStyle( fontSize: tokens.Dimensions.x5, fontWeight: FontWeight.w500, - height: tokens.Dimensions.x5 / tokens.Dimensions.x6, + height: tokens.Dimensions.x4 / tokens.Dimensions.x5, ); /// {@template zeta-type-heading-s} @@ -241,7 +207,7 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.headlineSmall]. /// {@endtemplate} - static const TextStyle zetaHeadingSmall = TextStyle( + static TextStyle zetaHeadingSmall = const TextStyle( fontSize: tokens.Dimensions.x6, fontWeight: FontWeight.w500, height: tokens.Dimensions.x7 / tokens.Dimensions.x6, @@ -255,7 +221,7 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.headlineMedium]. /// {@endtemplate} - static const TextStyle zetaHeadingMedium = TextStyle( + static TextStyle zetaHeadingMedium = const TextStyle( fontSize: tokens.Dimensions.x7, fontWeight: FontWeight.w500, height: tokens.Dimensions.x8 / tokens.Dimensions.x7, @@ -268,7 +234,7 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.headlineLarge]. /// {@endtemplate} - static const TextStyle zetaHeadingLarge = TextStyle( + static TextStyle zetaHeadingLarge = const TextStyle( fontSize: tokens.Dimensions.x8, fontWeight: FontWeight.w500, height: tokens.Dimensions.x9 / tokens.Dimensions.x8, @@ -282,11 +248,7 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.displaySmall]. /// {@endtemplate} - static const TextStyle zetaDisplaySmall = TextStyle( - fontSize: tokens.Dimensions.x9, - fontWeight: FontWeight.w300, - height: tokens.Dimensions.x9 / tokens.Dimensions.x10, - ); + static TextStyle zetaDisplaySmall = zetaHeadingSmall; /// {@template zeta-type-display-m} /// Medium display text. @@ -296,11 +258,7 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.displayMedium]. /// {@endtemplate} - static const TextStyle zetaDisplayMedium = TextStyle( - fontSize: tokens.Dimensions.x11, - fontWeight: FontWeight.w300, - height: tokens.Dimensions.x12 / tokens.Dimensions.x11, - ); + static TextStyle zetaDisplayMedium = zetaHeadingMedium; /// {@template zeta-type-display-l} /// Large display text. @@ -309,88 +267,16 @@ class ZetaText extends StatelessWidget { /// See also: /// * [TextTheme.displayLarge]. /// {@endtemplate} - static const TextStyle zetaDisplayLarge = TextStyle( - fontSize: tokens.Dimensions.x13, - fontWeight: FontWeight.w300, - height: tokens.Dimensions.x14 / tokens.Dimensions.x13, - ); - - /// {@template zeta-type-description} - /// Description text. - /// - /// This size falls off the mini unit scale, to meet very specific criteria, and forced to be used for single line text only. It never changes line height even in component design. - /// - /// Used for UI components and UI content design. - /// {@endtemplate} - static const TextStyle zetaDescription = TextStyle( - fontSize: tokens.Dimensions.x3_5, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x4 / tokens.Dimensions.x3_5, - ); - - /// {@macro zeta-type-responsive} - /// - /// {@macro zeta-type-heading-s} - static const TextStyle zetaHeadingSmallResponsive = TextStyle( - fontSize: tokens.Dimensions.x5, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x6 / tokens.Dimensions.x5, - ); - - /// {@macro zeta-type-responsive} - /// - /// {@macro zeta-type-heading-m} - static const TextStyle zetaHeadingMediumResponsive = TextStyle( - fontSize: tokens.Dimensions.x6, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x7 / tokens.Dimensions.x6, - ); - - /// {@macro zeta-type-responsive} - /// - /// {@macro zeta-type-heading-l} - static const TextStyle zetaHeadingLargeResponsive = TextStyle( - fontSize: tokens.Dimensions.x7, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x8 / tokens.Dimensions.x7, - ); - - /// {@macro zeta-type-responsive} - /// - /// {@macro zeta-type-display-s} - static const TextStyle zetaDisplaySmallResponsive = TextStyle( - fontSize: tokens.Dimensions.x8, - fontWeight: FontWeight.w300, - height: tokens.Dimensions.x9 / tokens.Dimensions.x8, - ); - - /// {@macro zeta-type-responsive} - /// - /// {@macro zeta-type-display-m} - static const TextStyle zetaDisplayMediumResponsive = TextStyle( - fontSize: tokens.Dimensions.x9, - fontWeight: FontWeight.w300, - height: tokens.Dimensions.x10 / tokens.Dimensions.x9, - ); - - /// {@template zeta-type-responsive} - /// Responsive text style, used for [DeviceType.mobileLandscape] and [DeviceType.mobilePortrait]. - /// {@endtemplate} - /// - /// {@macro zeta-type-display-l} - static const TextStyle zetaDisplayLargeResponsive = TextStyle( - fontSize: tokens.Dimensions.x11, - fontWeight: FontWeight.w300, - height: tokens.Dimensions.x12 / tokens.Dimensions.x11, - ); + static TextStyle zetaDisplayLarge = zetaHeadingLarge; /// Gets approximate char width based on width of O in IBM Plex Sans /// /// Only works for IBM Plex. - static double ch({double multiplier = _defaultChMultiplier, TextStyle style = zetaBodyMedium}) { + static double _ch({double multiplier = _defaultChMultiplier, TextStyle? style}) { + final setStyle = style ?? zetaBodyMedium; const plexCh = 0.6; - return multiplier * plexCh * (style.fontSize ?? tokens.Dimensions.x3); + return multiplier * plexCh * (setStyle.fontSize ?? tokens.Dimensions.x3); } /// The text to be displayed. @@ -405,7 +291,7 @@ class ZetaText extends StatelessWidget { /// /// See also: /// * [Text.style]. - final TextStyle style; + final TextStyle? style; /// Sets text color. /// @@ -413,9 +299,9 @@ class ZetaText extends StatelessWidget { /// * [TextStyle.color]. final Color? textColor; - /// Max width of Text box using [ch]. Not measured in dp / px. + /// Max width of Text box using [_ch]. Not measured in dp / px. /// - /// [ch] approximates width of a character using O as basis, so a maxWidth of 60 theoretically returns a max width containing 60 characters. + /// [_ch] approximates width of a character using O as basis, so a maxWidth of 60 theoretically returns a max width containing 60 characters. /// /// Only works with 'IBM Plex Sans'. final double? maxWidth; @@ -483,7 +369,7 @@ class ZetaText extends StatelessWidget { /// Constructor for [ZetaText]. const ZetaText( this.data, { - this.style = ZetaText.zetaBodyMedium, + this.style, this.resetHeight = false, this.textColor, this.fontSize, @@ -518,48 +404,66 @@ class ZetaText extends StatelessWidget { @override Widget build(BuildContext context) { - const TextStyle tempTextStyle = ZetaText.zetaBodyMedium; - final TextStyle thisStyle = tempTextStyle.copyWith( - fontSize: style.fontSize, - fontWeight: style.fontWeight, - height: style.height, + TextStyle thisStyle = (style ?? ZetaText.zetaBodyMedium).copyWith( + fontSize: style?.fontSize, + fontWeight: style?.fontWeight, + height: style?.height, ); String data = this.data ?? ''; final Color color = textColor ?? ZetaColors.of(context).textDefault; - TextStyle textStyle = context.deviceType.responsiveText ? thisStyle.mobileStyle : thisStyle; - textStyle = textStyle.copyWith( - fontSize: (fontSize ?? textStyle.fontSize ?? tokens.Typography.defaultTextSize) * + thisStyle = thisStyle.copyWith( + fontSize: (fontSize ?? thisStyle.fontSize ?? tokens.Typography.defaultTextSize) * MediaQuery.of(context).textScaleFactor, height: _fontSize, fontWeight: fontWeight, decoration: decoration ?? TextDecoration.none, fontStyle: fontStyle, color: color, + fontFamily: Theme.of(context).fontFamily, ); - if (resetHeight) textStyle = textStyle.copyWith(height: style == ZetaText.zetaDescription ? null : 1); + if (resetHeight) thisStyle = thisStyle.copyWith(height: 1); if (upperCase) data = data.toUpperCase(); return Padding( padding: _padding, child: maxWidth == null - ? Text(data, style: textStyle, textDirection: textDirection) + ? Text(data, style: thisStyle, textDirection: textDirection) : Align( alignment: textDirection == TextDirection.rtl ? Alignment.centerRight : Alignment.centerLeft, child: SizedBox( - width: maxWidth == null ? null : ch(multiplier: maxWidth ?? 0, style: textStyle), - child: Text(data, style: textStyle, textDirection: textDirection), + width: maxWidth == null ? null : _ch(multiplier: maxWidth ?? 0, style: thisStyle), + child: Text(data, style: thisStyle, textDirection: textDirection), ), ), ); } + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-body-xs} + ZetaText.bodyXSmall( + this.data, { + this.resetHeight = false, + this.maxWidth, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + super.key, + }) : style = zetaBodyXSmall; + /// {@macro zeta-component-text} /// /// {@macro zeta-type-body-s} - const ZetaText.bodySmall( + ZetaText.bodySmall( this.data, { this.resetHeight = false, this.maxWidth, @@ -578,7 +482,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-body-m} - const ZetaText.bodyMedium( + ZetaText.bodyMedium( this.data, { this.resetHeight = false, this.decoration, @@ -597,7 +501,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-body-l} - const ZetaText.bodyLarge( + ZetaText.bodyLarge( this.data, { this.resetHeight = false, this.decoration, @@ -616,7 +520,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-label-s} - const ZetaText.labelSmall( + ZetaText.labelSmall( this.data, { this.resetHeight = false, this.decoration, @@ -635,7 +539,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-label-m} - const ZetaText.labelMedium( + ZetaText.labelMedium( this.data, { this.resetHeight = false, this.decoration, @@ -654,7 +558,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-label-l} - const ZetaText.labelLarge( + ZetaText.labelLarge( this.data, { this.resetHeight = false, this.decoration, @@ -673,7 +577,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-title-s} - const ZetaText.titleSmall( + ZetaText.titleSmall( this.data, { this.resetHeight = false, this.decoration, @@ -692,7 +596,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-title-m} - const ZetaText.titleMedium( + ZetaText.titleMedium( this.data, { this.resetHeight = false, this.decoration, @@ -711,7 +615,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-title-l} - const ZetaText.titleLarge( + ZetaText.titleLarge( this.data, { this.resetHeight = false, this.decoration, @@ -730,7 +634,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-heading-s} - const ZetaText.headingSmall( + ZetaText.headingSmall( this.data, { this.resetHeight = false, this.decoration, @@ -749,7 +653,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-heading-m} - const ZetaText.headingMedium( + ZetaText.headingMedium( this.data, { this.decoration, this.fontSize, @@ -768,7 +672,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-heading-l} - const ZetaText.headingLarge( + ZetaText.headingLarge( this.data, { this.resetHeight = false, this.decoration, @@ -787,7 +691,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-display-s} - const ZetaText.displaySmall( + ZetaText.displaySmall( this.data, { this.resetHeight = false, this.decoration, @@ -806,7 +710,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-display-m} - const ZetaText.displayMedium( + ZetaText.displayMedium( this.data, { this.resetHeight = false, this.decoration, @@ -825,7 +729,7 @@ class ZetaText extends StatelessWidget { /// {@macro zeta-component-text} /// /// {@macro zeta-type-display-l} - const ZetaText.displayLarge( + ZetaText.displayLarge( this.data, { this.decoration, this.fontSize, @@ -840,23 +744,29 @@ class ZetaText extends StatelessWidget { this.maxWidth, super.key, }) : style = zetaDisplayLarge; + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(StringProperty('data', data)); + properties.add(DiagnosticsProperty('style', style)); + properties.add(ColorProperty('textColor', textColor)); + properties.add(DoubleProperty('maxWidth', maxWidth)); + properties.add(DoubleProperty('fontSize', fontSize)); + properties.add(DiagnosticsProperty('fontWeight', fontWeight)); + properties.add(EnumProperty('fontStyle', fontStyle)); + properties.add(DiagnosticsProperty('upperCase', upperCase)); + properties.add(DiagnosticsProperty('decoration', decoration)); + properties.add(EnumProperty('textDirection', textDirection)); + properties.add(DiagnosticsProperty('first', first)); + properties.add(DiagnosticsProperty('last', last)); + properties.add(DiagnosticsProperty('resetHeight', resetHeight)); + } +} - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-description} - const ZetaText.description( - this.data, { - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.resetHeight = false, - this.maxWidth, - super.key, - }) : style = zetaDescription; +/// Extension to add Zeta's extra small text size. +extension XSmall on TextTheme { + /// Smallest body text size. + TextStyle? get bodyXSmall { + return ZetaText.zetaBodyXSmall; + } } diff --git a/lib/theme/breakpoints.dart b/lib/src/theme/breakpoints.dart similarity index 100% rename from lib/theme/breakpoints.dart rename to lib/src/theme/breakpoints.dart diff --git a/lib/theme/colors.dart b/lib/src/theme/colors.dart similarity index 91% rename from lib/theme/colors.dart rename to lib/src/theme/colors.dart index c96b689e..198d8a22 100644 --- a/lib/theme/colors.dart +++ b/lib/src/theme/colors.dart @@ -2,7 +2,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// Zeta Colors. /// @@ -43,45 +43,59 @@ class ZetaColors { final ZetaColorSwatch _teal; final ZetaColorSwatch _pink; + final Color? _background; + final Color? _surface; + final Color? _white; + final Color? _black; + final Color? _onPrimary; final Color? _onSecondary; final Color? _onNegative; - final Color? _background; final Color? _onBackground; - final Color? _surface; final Color? _onSurface; - final Color? _white; - final Color? _black; + + final Map _generatedColors; static const _minShade = 10; - static const Color _defaultShadow = Color(0x1A49505E); - /// Generated color for use on [secondary]. + /// Generated color for use on [primary]. /// /// {@template zeta-color-on-X} /// If [secondary] is dark, [onSecondary] will be [textDarkMode]. /// /// If [secondary] is light, [onSecondary] will be [textLightMode]. /// {@endtemplate} - Color get onSecondary => - _onSecondary ?? - computeForeground( - input: secondary, - light: textDarkMode, - dark: textLightMode, - ); + Color get onPrimary { + if (_onPrimary != null) return _onPrimary!; + // if (_generatedColors['onPrimary'] != null) return _generatedColors['onPrimary']!; + _generatedColors['onPrimary'] = computeForegroundFromTheme(input: primary); + + return _generatedColors['onPrimary']!; + } /// Generated color for use on [secondary]. /// /// {@macro zeta-color-on-X} - Color get onPrimary => _onPrimary ?? computeForeground(input: primary, light: textDarkMode, dark: textLightMode); + Color get onSecondary { + if (_onSecondary != null) return _onSecondary!; + if (_generatedColors['onSecondary'] != null) return _generatedColors['onSecondary']!; + _generatedColors['onSecondary'] = computeForegroundFromTheme(input: secondary); + + return _generatedColors['onSecondary']!; + } /// Generated color for use on [negative]. /// /// {@macro zeta-color-on-X} - Color get onNegative => _onNegative ?? computeForeground(input: negative, light: textDarkMode, dark: textLightMode); + Color get onNegative { + if (_onNegative != null) return _onNegative!; + if (_generatedColors['onNegative'] != null) return _generatedColors['onNegative']!; + _generatedColors['onNegative'] = computeForegroundFromTheme(input: negative); + + return _generatedColors['onNegative']!; + } - /// Generated color for use on [surface]. + /// On surface color. /// /// {@macro zeta-color-on-X} Color get onSurface => _onSurface ?? textDefault; @@ -165,7 +179,7 @@ class ZetaColors { /// Background color. /// /// See [ColorScheme.background]. - Color get background => _background ?? surfacePrimary; + Color get background => _background ?? warm.shade10; /// On background color. /// @@ -195,7 +209,7 @@ class ZetaColors { /// /// * Light mode: `ZetaColors.cool.10`. /// * Dark mode: `ZetaColors.warm.30`. - Color get surfaceSecondary => isDarkMode ? warm.shade10 : cool.shade10; + Color get surfaceSecondary => isDarkMode ? cool.shade10 : white; /// Tertiary surface color. /// @@ -222,7 +236,7 @@ class ZetaColors { /// {@macro zeta-color-dark} /// /// {@macro zeta-color-aaa} - Color get positive => green.primary; + Color get positive => green.shade60; /// Red negative color. /// @@ -233,7 +247,7 @@ class ZetaColors { /// {@macro zeta-color-dark} /// /// {@macro zeta-color-aaa} - Color get negative => red.primary; + Color get negative => red.shade60; /// Orange warning color. /// @@ -425,7 +439,7 @@ class ZetaColors { List get rainbow => [red, orange, yellow, green, blue, teal, pink]; /// Default constructor for instance of [ZetaColors]. - const ZetaColors({ + ZetaColors({ ZetaColorSwatch primary = ZetaColorBase.blue, ZetaColorSwatch secondary = ZetaColorBase.blue, ZetaColorSwatch cool = ZetaColorBase.greyCool, @@ -442,7 +456,7 @@ class ZetaColors { Color linkVisitedLight = ZetaColorBase.linkVisitedLight, Color linkDark = ZetaColorBase.linkDark, Color linkVisitedDark = ZetaColorBase.linkVisitedDark, - this.shadow = _defaultShadow, + this.shadow = ZetaColorBase.shadow, this.isDarkMode = false, this.isAAA = false, Color? onPrimary, @@ -478,7 +492,8 @@ class ZetaColors { _surface = surface, _onSurface = onSurface, _black = black, - _white = white; + _white = white, + _generatedColors = {}; /// Creates a [ZetaColors] from individual colors and generates their full swatches with [ZetaColorSwatch.fromColor] ZetaColors.fromColors({ @@ -507,7 +522,7 @@ class ZetaColors { Color? onSurface, Color? black, Color? white, - this.shadow = _defaultShadow, + this.shadow = ZetaColorBase.shadow, this.isDarkMode = false, this.isAAA = false, }) : _primary = primary?.zetaColorSwatch ?? ZetaColorBase.blue, @@ -534,7 +549,8 @@ class ZetaColors { _surface = surface, _onSurface = onSurface, _black = black, - _white = white; + _white = white, + _generatedColors = {}; /// Returns a new ZetaColors instance, with the copied fields applied. ZetaColors copyWith({ @@ -585,7 +601,10 @@ class ZetaColors { Color light = ZetaColorBase.white, Color dark = ZetaColorBase.black, }) => - input.computeLuminance() > 0.5 ? dark : light; + input.isLight ? dark : light; + + /// Calculates foreground color based on luminance of input. + Color computeForegroundFromTheme({required Color input}) => input.isLight ? textDefault : textInverse; /// Setter for updating ZetaColors instance based on current context. static void setColors(BuildContext context, ZetaColors colors) { @@ -595,6 +614,14 @@ class ZetaColors { } } + /// Setter for updating if dark mode is activated for ZetaColors instance based on current context. + static void setDarkMode(BuildContext context, bool val) { + final ZetaState? state = context.findAncestorStateOfType(); + if (state != null) { + state.colors = state.colors.copyWith(isDarkMode: val); + } + } + /// Returns instance of [ZetaColors] from the current context. /// /// For this function to work properly, it is required that the current context is beneath a [ZetaColors] widget @@ -602,7 +629,8 @@ class ZetaColors { static ZetaColors of(BuildContext context) { final ZetaState? state = context.findAncestorStateOfType(); - return state?.colors ?? const ZetaColors(); + // ignore: prefer_const_constructors + return state?.colors ?? ZetaColors(); } } @@ -741,6 +769,9 @@ extension ColorExtension on Color { return hslColor.withLightness(percentage).toColor(); } + /// Uses [computeLuminance] to determine if a color if light. + bool get isLight => computeLuminance() > 0.5; + /// Gets lightness of color. double get lightness => HSLColor.fromColor(this).lightness; diff --git a/lib/theme/colors_base.dart b/lib/src/theme/colors_base.dart similarity index 97% rename from lib/theme/colors_base.dart rename to lib/src/theme/colors_base.dart index da47e689..36d2a5e6 100644 --- a/lib/theme/colors_base.dart +++ b/lib/src/theme/colors_base.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// Default set of Zeta Colors that can be used to make a [ZetaColors] instance. /// @@ -206,4 +206,7 @@ class ZetaColorBase { /// Visited link color for dark mode. static const Color linkVisitedDark = Color(0xFF47A3FF); + + /// Default shadow color. + static const Color shadow = Color(0x1A49505E); } diff --git a/lib/theme/constants.dart b/lib/src/theme/constants.dart similarity index 100% rename from lib/theme/constants.dart rename to lib/src/theme/constants.dart diff --git a/lib/theme/theme.dart b/lib/src/theme/theme.dart similarity index 79% rename from lib/theme/theme.dart rename to lib/src/theme/theme.dart index 9dfafb28..aed90f93 100644 --- a/lib/theme/theme.dart +++ b/lib/src/theme/theme.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; export 'breakpoints.dart'; export 'colors.dart'; @@ -34,8 +34,7 @@ class ZetaTheme { /// {@endtemplate} static ThemeData zetaLight({ZetaThemeData? initialTheme}) { return ThemeData( - colorScheme: - initialTheme?.colorScheme ?? initialTheme?.zetaColors?.toColorScheme ?? const ZetaColors().toColorScheme, + colorScheme: initialTheme?.colorScheme ?? initialTheme?.zetaColors?.toColorScheme ?? ZetaColors().toColorScheme, fontFamily: initialTheme?.fontFamily ?? 'packages/zeta_flutter/IBMPlexSans', // TODO(tokens): reinstate tokens.Typography.fontFamily when we have a plan for tokens textTheme: initialTheme?.textTheme ?? ZetaText.textTheme, @@ -49,7 +48,7 @@ class ZetaTheme { return ThemeData( colorScheme: initialTheme?.colorScheme ?? initialTheme?.zetaColors?.copyWith(isDarkMode: true).toColorScheme ?? - const ZetaColors().toColorScheme, + ZetaColors().toColorScheme, fontFamily: initialTheme?.fontFamily ?? 'packages/zeta_flutter/IBMPlexSans', textTheme: initialTheme?.textTheme ?? ZetaText.textTheme, ); @@ -61,7 +60,7 @@ class ZetaTheme { /// /// {@macro zeta-theme} static ThemeData builder({ZetaThemeData? initialTheme}) { - final ZetaColors colors = initialTheme?.zetaColors ?? const ZetaColors(); + final ZetaColors colors = initialTheme?.zetaColors ?? ZetaColors(); return ThemeData( colorScheme: initialTheme?.colorScheme ?? colors.toColorScheme, @@ -114,3 +113,16 @@ class ZetaThemeData { ); } } + +/// Font family for whole theme. +extension FontFamily on ThemeData { + /// Default font family used by theme. + /// + /// We assume that the same font should be used for all text styles in a theme, therefore we can extract from any child theme. + String? get fontFamily => textTheme.bodyMedium?.fontFamily; + + /// Default text color used by theme. + /// + /// We assume that the same font should be used for all text styles in a theme, therefore we can extract from any child theme. + Color? get defaultColor => textTheme.bodyMedium?.color; +} diff --git a/lib/tokens.dart b/lib/src/tokens.dart similarity index 99% rename from lib/tokens.dart rename to lib/src/tokens.dart index 4d44d476..00ad26c4 100644 --- a/lib/tokens.dart +++ b/lib/src/tokens.dart @@ -1,4 +1,4 @@ -import '../zeta_flutter.dart'; +import '../../zeta_flutter.dart'; /// Tokens that are used for [ZetaSpacing]. /// diff --git a/lib/utils/extensions.dart b/lib/src/utils/extensions.dart similarity index 100% rename from lib/utils/extensions.dart rename to lib/src/utils/extensions.dart diff --git a/lib/src/zeta.dart b/lib/src/zeta.dart new file mode 100644 index 00000000..085224d5 --- /dev/null +++ b/lib/src/zeta.dart @@ -0,0 +1,116 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; + +/// Wrapper widget for apps using zeta. +/// +/// Please place this widget at the top level of the application. +/// Typically this would be wrapping a [MaterialApp], [WidgetsApp] or [CupertinoApp]. +/// +/// Without this widget in the tree, theming and colors may not work. +class Zeta extends StatefulWidget { + /// Base theme for the app. Zeta styles will be applied on top of this. + final ZetaThemeData? theme; + + /// Override for custom colors. + final ZetaColors? colors; + + /// Builder for the app. + /// + /// Returns theme and colors. + final Widget Function(BuildContext, ThemeData, ZetaColors) builder; + + /// Constructor for [Zeta]. + const Zeta({required this.builder, this.theme, this.colors, super.key}); + @override + State createState() => ZetaState(); + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('theme', theme)); + properties.add(DiagnosticsProperty('colors', colors)); + properties + .add(ObjectFlagProperty.has('builder', builder)); + } +} + +/// State for [Zeta]. +class ZetaState extends State { + ZetaColors _colors = ZetaColors(); + late ThemeData _theme; + late ZetaThemeData _zetaTheme; + + /// Theme used by zeta. + ZetaThemeData get zetaTheme => _zetaTheme; + set zetaTheme(ZetaThemeData value) { + _zetaTheme = value; + setState(() { + _theme = ZetaTheme.builder(initialTheme: zetaTheme); + }); + } + + bool _ready = false; + + /// Colors for app. + /// + /// Access using `ZetaColors.of(context)`. + ZetaColors get colors => _colors; + + /// Sets colors for app. + /// + /// Access using `ZetaColors.setColors(context, colors)`. + /// + /// When called, resets top-level key to force UI rebuild of app. + set colors(ZetaColors value) { + if (_colors != value) { + setState(() { + _colors = value; + _theme = ZetaTheme.builder(initialTheme: zetaTheme.copyWith(zetaColors: value)); + }); + } + } + + @override + void initState() { + super.initState(); + + zetaTheme = (widget.theme ?? const ZetaThemeData()).copyWith(zetaColors: colors); + colors = widget.colors ?? ZetaColors(); + _ready = true; + } + + @override + void didUpdateWidget(Zeta oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.colors != widget.colors) { + colors = widget.colors ?? ZetaColors(); + zetaTheme = (widget.theme ?? const ZetaThemeData()).copyWith(zetaColors: colors); + } + if (oldWidget.theme != widget.theme) { + zetaTheme = (widget.theme ?? const ZetaThemeData()).copyWith(zetaColors: colors); + } + } + + @override + Widget build(BuildContext context) { + if (_ready) { + return Theme( + data: _theme, + child: Builder( + builder: (context) => widget.builder(context, _theme, colors), + ), + ); + } + + return const SizedBox(); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('colors', colors)); + properties.add(DiagnosticsProperty('zetaTheme', zetaTheme)); + } +} diff --git a/lib/zeta.dart b/lib/zeta.dart deleted file mode 100644 index 41beb933..00000000 --- a/lib/zeta.dart +++ /dev/null @@ -1,93 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -import '../zeta_flutter.dart'; - -/// Wrapper widget for apps using zeta. -/// -/// Please place this widget at the top level of the application. -/// Typically this would be wrapping a [MaterialApp], [WidgetsApp] or [CupertinoApp]. -/// -/// Without this widget in the tree, theming and colors may not work. -class Zeta extends StatefulWidget { - /// Base theme for the app. Zeta styles will be applied on top of this. - final ZetaThemeData? theme; - - /// Override for custom colors. - final ZetaColors colors; - - /// Builder for the app. - /// - /// Returns theme and colors. - final Widget Function(BuildContext, ThemeData, ZetaColors) builder; - - /// Constructor for [Zeta]. - const Zeta({required this.builder, this.theme, this.colors = const ZetaColors(), super.key}); - @override - State createState() => ZetaState(); -} - -/// State for [Zeta]. -class ZetaState extends State { - ZetaColors _colors = const ZetaColors(); - GlobalKey _key = GlobalKey(); - ThemeData _theme = ThemeData(); - bool _ready = false; - - /// Colors for app. - /// - /// Access using `ZetaColors.of(context)`. - ZetaColors get colors => _colors; - - /// Sets colors for app. - /// - /// Access using `ZetaColors.setColors(context, colors)`. - /// - /// When called, resets top-level key to force UI rebuild of app. - set colors(ZetaColors value) { - if (_colors != value) { - setState(() { - _colors = value; - _key = GlobalKey(); - _theme = ZetaTheme.builder(initialTheme: (widget.theme ?? const ZetaThemeData()).copyWith(zetaColors: value)); - }); - } - } - - @override - void initState() { - super.initState(); - - colors = widget.colors; - _theme = ZetaTheme.zetaLight(initialTheme: widget.theme); - _ready = true; - } - - @override - void didUpdateWidget(Zeta oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.colors != widget.colors) { - colors = widget.colors; - } - } - - @override - Widget build(BuildContext context) { - if (_ready) { - return Material( - child: DefaultTextStyle( - style: ZetaText.zetaBodyMedium.copyWith( - decoration: TextDecoration.none, - ), - child: Theme( - key: _key, - data: _theme, - child: Builder(builder: (context) => widget.builder(context, _theme, colors)), - ), - ), - ); - } - - return const SizedBox(); - } -} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 4c18476d..b657f5bc 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -1,11 +1,11 @@ /// Zebra Design System (Zeta) - Flutter Component Library library zeta_flutter; -export 'components/grid.dart'; -export 'components/spacing.dart'; -export 'components/text.dart'; -export 'theme/constants.dart'; -export 'theme/theme.dart'; -export 'tokens.dart'; -export 'utils/extensions.dart'; -export 'zeta.dart'; +export 'src/components/grid.dart'; +export 'src/components/spacing.dart'; +export 'src/components/text.dart'; +export 'src/theme/constants.dart'; +export 'src/theme/theme.dart'; +export 'src/tokens.dart'; +export 'src/utils/extensions.dart'; +export 'src/zeta.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 3d05ee2c..3cc6946f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,10 @@ name: zeta_flutter +version: 0.0.1+12 description: Zebra Design System (Zeta) - Flutter Component Library -version: 0.0.1+11 -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 platforms: android: @@ -28,10 +31,10 @@ flutter: fonts: - family: IBMPlexSans fonts: - - asset: lib/assets/fonts/IBMPlexSans-Light.otf + - asset: lib/src/assets/fonts/IBMPlexSans-Light.otf weight: 300 - - asset: lib/assets/fonts/IBMPlexSans-Regular.otf + - asset: lib/src/assets/fonts/IBMPlexSans-Regular.otf weight: 400 - - asset: lib/assets/fonts/IBMPlexSans-Medium.otf + - asset: lib/src/assets/fonts/IBMPlexSans-Medium.otf weight: 500 uses-material-design: true From 199328c28ccfa8a05a1494c08ad93aaf13dd3b28 Mon Sep 17 00:00:00 2001 From: Luke Date: Wed, 29 Nov 2023 13:07:54 +0000 Subject: [PATCH 02/41] Update to mirror 0.1.0+1 from ZebraDevs --- .github/workflows/onMerge.yml | 8 +- .github/workflows/pr.yml | 4 +- .gitignore | 138 +- .pubignore | 1 + CHANGELOG.md | 83 +- LICENSE-3RD-PARTY | 11 + README.md | 85 +- analysis_options.yaml | 42 +- custom_docs/components/Color/flutter.md | 102 ++ custom_docs/components/Grid/flutter.md | 59 + custom_docs/components/Spacing/flutter.md | 198 +++ custom_docs/components/Typography/flutter.md | 98 ++ custom_docs/flutter.template.md | 66 + example/android/build.gradle | 2 +- example/ios/Podfile.lock | 2 +- .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - example/lib/home.dart | 46 +- example/lib/main.dart | 21 +- example/lib/pages/color_example.dart | 239 +-- example/lib/pages/grid_example.dart | 20 +- example/lib/pages/spacing_example.dart | 15 +- example/lib/pages/theme_color_switch.dart | 69 + example/lib/pages/theme_constrast_switch.dart | 56 + example/lib/pages/theme_mode_switch.dart | 60 + example/lib/pages/typography_example.dart | 29 +- example/lib/widgets.dart | 38 +- example/macos/Podfile.lock | 2 +- example/pubspec.lock | 50 +- example/pubspec.yaml | 4 +- example/test/color_test.dart | 10 +- example/test/test_components.dart | 13 +- example/test/typography_test.dart | 4 +- .../components/color_widgetbook.dart | 33 +- .../components/typography_widgetbook.dart | 7 +- example/widgetbook/widgetbook.dart | 2 +- lib/src/components/grid.dart | 35 +- lib/src/components/spacing.dart | 38 +- lib/src/components/text.dart | 994 ++++++------- lib/src/theme/breakpoints.dart | 45 +- lib/src/theme/color_extensions.dart | 305 ++++ lib/src/theme/color_scheme.dart | 171 +++ lib/src/theme/color_swatch.dart | 197 +++ lib/src/theme/colors.dart | 1302 ++++++++++------- lib/src/theme/colors_base.dart | 280 ++-- lib/src/theme/constants.dart | 20 + lib/src/theme/contrast.dart | 149 ++ lib/src/theme/theme.dart | 128 -- lib/src/theme/theme_data.dart | 97 ++ lib/src/theme/theme_service.dart | 25 + lib/src/tokens.dart | 3 - lib/src/zeta.dart | 382 ++++- lib/zeta_flutter.dart | 6 +- pubspec.yaml | 12 +- 54 files changed, 4031 insertions(+), 1791 deletions(-) create mode 100644 .pubignore create mode 100644 LICENSE-3RD-PARTY create mode 100644 custom_docs/components/Color/flutter.md create mode 100644 custom_docs/components/Grid/flutter.md create mode 100644 custom_docs/components/Spacing/flutter.md create mode 100644 custom_docs/components/Typography/flutter.md create mode 100644 custom_docs/flutter.template.md delete mode 100644 example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 example/lib/pages/theme_color_switch.dart create mode 100644 example/lib/pages/theme_constrast_switch.dart create mode 100644 example/lib/pages/theme_mode_switch.dart create mode 100644 lib/src/theme/color_extensions.dart create mode 100644 lib/src/theme/color_scheme.dart create mode 100644 lib/src/theme/color_swatch.dart create mode 100644 lib/src/theme/contrast.dart delete mode 100644 lib/src/theme/theme.dart create mode 100644 lib/src/theme/theme_data.dart create mode 100644 lib/src/theme/theme_service.dart diff --git a/.github/workflows/onMerge.yml b/.github/workflows/onMerge.yml index 01f42b4d..18736e3c 100644 --- a/.github/workflows/onMerge.yml +++ b/.github/workflows/onMerge.yml @@ -23,7 +23,7 @@ jobs: with: files: | **/*.dart - docs/* + custom-docs/* **/*.yaml **/*.yml files_ignore: example/* @@ -41,7 +41,7 @@ jobs: - name: Run step if any *.js file(s) or any file in the static folder change if: steps.changed-files-excluded.outputs.any_changed == 'true' run: | - echo "One or more *.js file(s) or any file in the static folder but not in the doc folder has changed." + echo "One or more *.js file(s) or any file in the static folder but not in the custom-docs folder has changed." echo "List all the files that have changed: ${{ steps.changed-files-excluded.outputs.all_changed_files }}" - name: Change flutter version tag uses: BentEngbers/flutter-change-version@v1.0.3 @@ -116,13 +116,13 @@ jobs: env: API_TOKEN_GITHUB: ${{ secrets.PAT }} with: - source_file: "docs/" + source_file: "custom-docs/" destination_repo: "zebratechnologies/zeta" destination_folder: "./" destination_branch: "flutter/${{ steps.read-version.outputs.version-number }}" user_email: "github-actions@github.com" user_name: "github-actions" - commit_message: "flutter docs" + commit_message: "flutter doc" - name: Open Zeta PR uses: thecanadianroot/open-pull-request-action@v1.0.3 with: diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index c74d4c29..6b5bcf3a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -14,7 +14,7 @@ jobs: fetch-depth: 0 ref: main persist-credentials: false - - name: Get all changed *.dart, files in docs or pubspec.yaml + - name: Get all changed *.dart, files in custom-docs or pubspec.yaml id: changed-files uses: tj-actions/changed-files@v35 with: @@ -22,7 +22,7 @@ jobs: sha: ${{ github.event.pull_request.head.sha }} files: | **/*.dart - docs + custom-docs pubspec.yaml analyze: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index f8ef7c9c..369fe7d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -# Miscellaneous *.class *.log *.pyc @@ -9,27 +8,140 @@ .history .svn/ migrate_working_dir/ - -# IntelliJ related *.iml *.ipr *.iws .idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. .vscode/settings.json - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. /pubspec.lock **/doc/api/ .dart_tool/ .packages build/ - -.vscode/settings.json .flutter-plugins .flutter-plugins-dependencies -**/.fvm/ \ No newline at end of file +**/.fvm/ +.gradle/ +local.properties +*.log +captures/ +.externalNativeBuild/ +.cxx/ +*.apk +output.json +misc.xml +deploymentTargetDropDown.xml +render.experimental.xml +*.jks +*.keystore +google-services.json +*.hprof +gen-external-apklibs +Pods/ +pubspec.lock +doc/api/ +.env* +*.dart.js +*.info.json +*.js_ +*.js.deps +*.js.map +.env +.fvm/flutter_sdk +.pub-cache/ +.pub/ +coverage/ +lib/generated_plugin_registrant.dart +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/key.properties +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/.last_build_id +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +*.asp +*.cer +*.csr +*.css +*.htm +*.js +*.jsp +*.php +*.rss +*.wasm +*.wat +*.xhtml +xcuserdata/ +*.xcscmblueprint +*.xccheckout +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcodeproj/project.xcworkspace/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno +**/xcshareddata/WorkspaceSettings.xcsettings +.AppleDouble +.LSOverride +Icon +._* +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +*.icloud +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db +*.stackdump +[Dd]esktop.ini +$RECYCLE.BIN/ +*.cab +*.msi +*.msix +*.msm +*.msp +*.lnk +**/Generated.xcconfig diff --git a/.pubignore b/.pubignore new file mode 100644 index 00000000..33e41fc7 --- /dev/null +++ b/.pubignore @@ -0,0 +1 @@ +custom_docs/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 71a19d7b..2d554425 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,87 @@ +## [0.1.0+1] - 2023-11-28 + +- chore: Tidy, reorganise and prepare repo + +docs: update changelog and documentation + +feat(type): Add xSmall and conform to latest figma designs. + +- "Refactored the ZetaColors class for better customization + +The ZetaColors class was heavily refactored for better customization of variables such as brightness, contrast, color swatches, and additional color attributes. Several fields were made final for the overall class safety. This change improves color control on different themes for the application." + +- "Updated the ZetaColor and Theme setup to use InheritedWidget + +The ZetaDefaults class was updated to Zeta inheriting from InheritedWidget. This change allows easy access to the Zeta theme settings (contrast, theme mode, theme data, color set) from anywhere in the widget tree. The ZetaAppBuilder function was updated to take in ThemeData and ThemeMode. The ZetaProvider was added to provide Zeta theming and contrast data down the widget tree. The code for the color and typography examples was adjusted to use the new Zeta context extension, instead of using Theme.of(context) to get colorScheme. This change was crucial to simplify the process of adapting the application visuals to different themes." + +- "Improve theme management functionality in Zeta + +Removed code concerning getting a color's RGB hex code from 'color_extensions.dart', as it was seldom used. Updated 'zeta_flutter.dart' to unhide ZetaColorGetters. Adaptations in 'zeta.dart' included switching mediaBrightness to \_mediaBrightness for internal use and adding methods for accurate determination of color set and brightness settings based on the theme mode. Also, ZetaProvider was updated for 'system' theme mode support. example/lib/main.dart and example/lib/widgets.dart were updated to support these changes, including UI updates for seamless theme switching." + +- "Add theme update function and extend ZetaColorGetters + +Implemented a method in 'zeta.dart' to support updating the current theme data dynamically. Extended 'color_scheme.dart' by introducing \_ZetaColorProperties and updating ZetaColorGetters. These changes increase flexibility for theme management and provide a structured and accessible way to get Zeta colors through the theme context." + +- Remove theme_extensions.dart and move contents to colors.dart + +Theme extensions were deleted and its contents were moved to colors.dart to consolidate all color-related codes in one file for easier navigation and editing. Additional enhancements include optimizing color assignments and making ZetaColors immutable for more robust color management. + +- Refactor code for color theme and add theme switcher + +Refactored codebase to improve the color theme handling: relocated theme related methods to colors.dart from theme_extensions.dart for consolidated color theme data. Optimized color assignments by leveraging the 'copyWith' method, allowing more efficient color management. Introduced the immutability of ZetaColors to enhance robustness. Bumped version in pubspec.yaml to 0.0.1+13 due to these changes. Renamed theme.dart to theme_data.dart for more semantic file naming. Added 'identifier' to the ZetaThemeData for easier theme identification. +The visible application change is an added ThemeSwitcher in the example app, offering a UI to switch between different predefined themes. + +- Add ZetaThemeService and theme switcher in example app + +Implemented ZetaThemeService as an abstract class, providing structure for loading and saving themes within the app. Removed an obsolete comment within the contrast.dart and made necessary imports in zeta.dart. Asynchronous theme loading is added during app startup and saving is done upon theme updates. Also, for user-interaction, an exclusive ThemeSwitcher widget is added in the example app allowing users to select between available themes. This improves user experience, and optimizes theme handling and application performance. + +- Refactor color swatch generation to utilize zeta + +Refactored color swatch generation in color_example.dart to use Zeta instead of directly using the Theme. Now the brightness for ZetaColorSwatch is being pulled from zeta object rather than theme. This ensures consistency across different parts of the application where Zeta is used. Also changed theme.colorScheme.surface to colors.surfacePrimary for better readability, and alignment with use of zeta object. + +- Add icon colors to color scheme + +Extended the color scheme in colors.dart to include default, subtle, disabled, and inverse icon colors. These were added to ensure consistent icon colors across the application and support dark mode by allowing inverted color swatches. + +- Refactor theme switch settings and add new features + +Renamed 'theme_switch.dart' to 'theme_color_switch.dart' and added two new files 'theme_contrast_switch.dart' and 'theme_mode_switch.dart' in order to separate the theme settings logically into distinct features - Theme Color Switch, Theme Contrast Switch and Theme Mode Switch respectively. Also, the theme application feature has been refactored within 'widgets.dart' to use the newly created theme features instead of the old theme switch. This enhances modularity and the user's ability to switch theme settings easily. + +- Update method naming for consistent architecture in text.dart + +Changed the method name 'withColor' to 'themeWithColor' in text.dart for consistency with other part of the architecture and for better readability. This change supports the shift towards a consistently designed application architecture and helps developers easily decipher the role of the method in the code. + +- Update color scheme mapping and library version in colors.dart and pubspec.lock + +Refined the color mapping in ZetaColorScheme in colors.dart by replacing effectiveSurfaceTertiary with textDefault, enhancing the clarity of backdrop's color role. Concurrently, version of multiple dependencies in pubspec.lock are updated to benefit from recent fixes and improvements in those libraries. + +- Change `Color` to `ZetaColorSwatch` in theme files + +Adjusted the class references in colors.dart from `Color` to `ZetaColorSwatch` to provide a more consistent color swatch across the app. The swatch allows for more flexibility in using color variations. Adjustments were also made in color_scheme.dart and color_swatch.dart to include better explanatory messages and use standard dart documentation format. Changes in custom_docs/components/Color/flutter.md were made to align with these updates. + +- Enhance contrast and color handling in theme files + +Removed 'flutter.md' as it is no longer required due to improvements made in contrast and color handling. For better accessibility support, 'contrast.dart' was refactored for better contrast handling and 'color_extensions.dart' now includes a mechanism to generate color swatch based on contrast ratio. Also, 'zeta.dart' was updated to adapt to the system's brightness providing better user experience. Overall, these adjustments aim to enhance accessibility and user experience, apart from simplifying the codebase. + +- Add LICENSE-3RD-PARTY for third-party libraries + +Introduced license details for third-party libraries used in the project. MIT license applies to 'tinycolor' and SIL Open Font License applies to 'IBMPlexSans'. This ensures proper acknowledgement and licensure compliance for used third-party resources. + +- Set up with ZDS Analysis + ## [0.0.1+12] - 2023-09-06 + ### :wrench: Chores -- [`6a2834e`](https://github.com/zebratechnologies/zeta-flutter/commit/6a2834e762c238d3927d83a239490250b1687b64) - Tidy, reorganise and prepare repo *(commit by [@thelukewalton](https://github.com/thelukewalton))* + +- [`6a2834e`](https://github.com/zebratechnologies/zeta-flutter/commit/6a2834e762c238d3927d83a239490250b1687b64) - Tidy, reorganise and prepare repo _(commit by [@thelukewalton](https://github.com/thelukewalton))_ ### :flying_saucer: Other Changes + - [`f91e8ef`](https://github.com/zebratechnologies/zeta-flutter/commit/f91e8ef85c0a1670227d66bd441513bc33e6242c) - Feature/color ([#21](https://github.com/zebratechnologies/zeta-flutter/pull/21)) * feat(color): Adding color defs -* feat(color): starting colorswatch util +* feat(color): starting colorswatch util * bug(quality): updating lint rules @@ -15,8 +89,7 @@ * bug(platforms): adding windows into example -* bug(type): Fixing reset height and tests failing *(commit by [@thelukewalton](https://github.com/thelukewalton))* - +* bug(type): Fixing reset height and tests failing _(commit by [@thelukewalton](https://github.com/thelukewalton))_ ## 0.0.1+11 - 2023-08-09 @@ -103,4 +176,4 @@ - Initial setup -[0.0.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+11...0.0.1+12 \ No newline at end of file +[0.0.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+11...0.0.1+12 diff --git a/LICENSE-3RD-PARTY b/LICENSE-3RD-PARTY new file mode 100644 index 00000000..75e911fe --- /dev/null +++ b/LICENSE-3RD-PARTY @@ -0,0 +1,11 @@ +--- + + MIT + applies to: + - tinycolor + + SIL Open Font License, Version 1.1 + applies to: + - IBMPlexSans + +--- diff --git a/README.md b/README.md index 284d1448..eb8c75bd 100644 --- a/README.md +++ b/README.md @@ -2,28 +2,87 @@ Zeta is the new, formal, standardized Zebra Design System based off the successes of ZDS (Zebra Design System). -Note: This package is in pre-release, and so many aspects are incomplete. +> 🚧 **Note**: This package is in pre-release, and so many aspects are incomplete. -# Usage +## Installation -[Install zeta_flutter](https://pub.dev/packages/zeta_flutter/install) +To install `zeta_flutter`, follow the instructions [here](https://pub.dev/packages/zeta_flutter/install). -Zeta extends the use of Flutter's built in theming tools, and so to work correctly your app needs to be wrapped with the zeta theme as such: +## Usage +Zeta offers flexibility in theming through its `ZetaProvider` widget. Here's a breakdown of its features: + +### Setting the Initial Theme Mode + +Zeta allows you to specify an initial theme mode for your app, which can be one of the following: + +- `ThemeMode.system`: Adheres to the system's theme. +- `ThemeMode.light`: Uses the light theme mode. +- `ThemeMode.dark`: Uses the dark theme mode. + +By default, the theme mode is set to `ThemeMode.system`. + +```dart +initialThemeMode: ThemeMode.light +``` + +### Providing Initial Theme Data + +You can provide the initial theme data for the app which contains all the theming information. If you don't specify one, it will default to a basic instance of `ZetaThemeData`. + +```dart +initialThemeData: ZetaThemeData() +``` + +### Setting the Initial Contrast + +Zeta also lets you define the initial contrast setting for your app. By default, it's set to `ZetaContrast.aa`. + +```dart +initialContrast: ZetaContrast.aa +``` + +### Building Your App with Zeta Theming + +The `builder` function is used to construct the widget tree with the provided theming information. This function is expected to receive a `BuildContext`, `ZetaThemeData`, and `ThemeMode` as arguments, and it should return a `Widget`. + +```dart +builder: (context, themeData, themeMode) { + // Your app's widget tree here +} +``` + +### Constructing the ZetaProvider + +To tie everything together, use the `ZetaProvider` constructor. The `builder` argument is mandatory, while the others are optional but allow you to set initial values: ```dart @override Widget build(BuildContext context) { - return Zeta( - builder: (context, theme, colors) { - return MaterialApp.router(theme: theme, routerConfig: router); + return ZetaProvider( + builder: (context, themeData, themeMode) { + final dark = themeData.colorsDark.toScheme(); + final light = themeData.colorsLight.toScheme(); + return MaterialApp.router( + routerConfig: router, + themeMode: themeMode, + theme: ThemeData( + fontFamily: themeData.fontFamily, + scaffoldBackgroundColor: light.background, + colorScheme: light, + ), + darkTheme: ThemeData( + fontFamily: themeData.fontFamily, + scaffoldBackgroundColor: dark.background, + colorScheme: dark, + ), + ); }, ); } ``` -This returns the Zeta theme and colors, which will be used across the app. Custom `ThemeData` and `ZetaColor` objects can be passed in to apply custom themes and colors. - +With these configurations, Zeta makes it easy to achieve consistent theming throughout your Flutter application. ## Viewing the components To view examples of all the components in the library, you can run the example app in this repo or go to [Zeta](https://zeta-ds.web.app/) @@ -33,11 +92,3 @@ To view examples of all the components in the library, you can run the example a This software is licensed with the MIT license (see [LICENSE](./LICENSE)). --- - -### Pre release TODOs - -[ ] TODO: update actions - -[ ] TODO: Make public repo - -[ ] TODO: Add to pub.dev diff --git a/analysis_options.yaml b/analysis_options.yaml index b689dcb6..6bfc3f6f 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,41 +1 @@ -include: all_lint_rules.yaml -analyzer: - exclude: - - "**/*.g.dart" - - "**/*.freezed.dart" - - "test/.test_coverage.dart" - - "bin/cache/**" - - "lib/generated_plugin_registrant.dart" - - language: - strict-casts: true - strict-inference: true - strict-raw-types: true - - errors: - included_file_warning: ignore - missing_required_param: error - missing_return: error - deprecated_member_use_from_same_package: ignore - parameter_assignments: warning - -linter: - rules: - always_put_control_body_on_new_line: false - always_put_required_named_parameters_first: false - always_specify_types: false - always_use_package_imports: false - avoid_classes_with_only_static_members: false - avoid_positional_boolean_parameters: false - avoid_types_on_closure_parameters: false - cascade_invocations: false - close_sinks: false - lines_longer_than_80_chars: false - omit_local_variable_types: false - prefer_constructors_over_static_methods: false - prefer_double_quotes: false - prefer_expression_function_bodies: false - prefer_final_parameters: false - prefer_int_literals: false - sort_constructors_first: false - unnecessary_final: false +include: package:zds_analysis/analysis_options_lib.yaml diff --git a/custom_docs/components/Color/flutter.md b/custom_docs/components/Color/flutter.md new file mode 100644 index 00000000..b183f74b --- /dev/null +++ b/custom_docs/components/Color/flutter.md @@ -0,0 +1,102 @@ +## ZetaColors Usage + +To import ZetaColors into a Dart file: + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; +``` + +### Example + +ZetaColors should be an app-wide parameter, to ensure colors throughout an app stay consistent. As such, it should be created at the highest level of an app, from where it can be distributed. + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; + +class MyApp extends StatelessWidget{ + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + + /// Build colors object with custom colors. + final ZetaColors colors = ZetaColors( + /// Add custom colors here. + ); + + /// Wrap whole app with [Zeta] to provide theming. + return Zeta( + colors: colors, + builder: (BuildContext context, ThemeData theme, ZetaColors colors) => ZetaColorExample(), + ); + } +} + +class ZetaColorExample extends StatelessWidget{ + const ZetaColorExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + + + final ZetaColors colors = ZetaColors.of(context); + + return Container( + color: colors.red, + ); + } +} + +``` + +### ZetaColors + +ZetaColors provides a full range of colors to be used, with various modifiers to return colors based on function. + +The following colors are provided as `ZetaColorSwatch`: + +- primary +- secondary +- cool (grey) +- warm (grey) +- blue +- red +- green +- orange +- purple +- yellow +- teal +- pink + +When creating a custom ZetaColors object, colors should be provided as a full `ZetaColorSwatch`, unless you want to use the default values, which are described in `ZetaColorBase`. + +ZetaColors has the following modifiers: + +- primary, onPrimary +- secondary, onSecondary +- positive, onPositive, negative, onNegative, warning, onWarning, info, onInfo +- surface, onSurface, surfaceDisabled, surfaceHovered, surfaceSecondary, surfaceTertiary, surfaceSelectedHovered, surfaceSelected +- background, onBackground +- textDefault, textSubtle, textDisabled, textInverse, +- borderDefault, borderSubtle, borderDisabled, borderSelected, +- white, black +- link, linkVisited, +- textLightMode, textDarkMode + +Commonly, `ZetaColors.toColorScheme` should be used to create a color scheme for use with `MaterialApp`. + +### ZetaColorSwatch + +ZetaColorSwatch returns a swatch of colors with shades at 10, 20, 30, 40, 50, 60, 70, 80, 90 and 100 where the higher the value, the darker the color. + +ZetaColorSwatch has the following modifiers: + +- primary +- icon +- border, borderSubtle +- surface +- subtle +- on +- disabled + +ZetaColorSwatch can be generated from a single color, but this is not recommended as results may not look as expected, and will probably not conform to any accessability requirements. diff --git a/custom_docs/components/Grid/flutter.md b/custom_docs/components/Grid/flutter.md new file mode 100644 index 00000000..0edc52d2 --- /dev/null +++ b/custom_docs/components/Grid/flutter.md @@ -0,0 +1,59 @@ +## ZetaGrid Usage + +To import ZetaGrid into a Dart file: + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; +``` + +### Example + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; +class ZetaGridExample extends StatelessWidget{ + const ZetaGridExample({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return ZetaGrid(...); + } +} +``` + +### Setup + +To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: + +```dart +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/src/theme/theme.dart'; +class MyApp extends StatelessWidget { + const MyApp({super.key}); + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ZetaTheme.zeta, + builder: (context, child) => ..., + ); + } +} +``` + +or + +```dart +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/src/theme/theme.dart'; +class MyApp extends StatelessWidget { + const MyApp({super.key}); + @override + Widget build(BuildContext context) { + return Theme( + data: ZetaTheme.zeta, + child: CupertinoApp( + builder: (context, child) => ..., + ), + ); + } +} +``` diff --git a/custom_docs/components/Spacing/flutter.md b/custom_docs/components/Spacing/flutter.md new file mode 100644 index 00000000..6eddb8b6 --- /dev/null +++ b/custom_docs/components/Spacing/flutter.md @@ -0,0 +1,198 @@ +## ZetaSpacing Usage + +To import ZetaSpacing into a Dart file: + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; +``` + +### Example + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ZetaSpacingExample extends StatelessWidget{ + const ZetaSpacingExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ZetaSpacing(...); + } +} +``` + +### Setup + +To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: + +```dart +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/src/theme/theme.dart'; + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ZetaTheme.zeta, + builder: (context, child) => ..., + ); + } +} +``` + +or + +```dart + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/src/theme/theme.dart'; + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return Theme( + data: ZetaTheme.zeta, + child: CupertinoApp( + builder: (context, child) => ..., + ), + ); + } +} +``` + +### ZetaSpacing + +ZetaSpacing provides four options for spacing + +- `square` - applies inset to all 4 sides equally. +- `squish` - applies inset to top and bottom only. +- `inline` - applies inset to start and end only. +- `inlineStart` - applies inset to start only. For LTR locales this is the left, for RTL locales this is the right. +- `inlineEnd` - applies inset to end only. For LTR locales this is the right, for RTL locales this is the left. +- `stack` - applies inset to bottom only. + +These spacings should be applied with the following doubles: + +- `x0` - 0 +- `x1` - 4 - also `xxs` +- `x2` - 8 - also `xs` +- `x3` - 12 - also `s` +- `x4` - 16 - also `b` +- `x5` - 20 +- `x6` - 24 - also `m` +- `x7` - 28 +- `x8` - 32 - also `l` +- `x9` - 36 +- `x10` - 40 +- `x11` - 44 +- `x12` - 48 +- `x13` - 52 +- `x14` - 58 +- `x16` - 64 - also `xl` +- `x20` - 80 - also `xxl` +- `x24` - 96 - also `xxxl` + +Spacing components can be used in multiple ways: + +### ZetaSpacing() widget with named constructors. + +```dart +const ZetaSpacing.square( + Text('Example'), + size: Dimensions.x1, +), +const ZetaSpacing.squish( + Text('Example'), + size: Dimensions.x1, +), +const ZetaSpacing.stack( + Text('Example'), + size: Dimensions.x1, +) +const ZetaSpacing.inline( + Text('Example'), + size: Dimensions.x1, +) +``` + +This is the preferred way to use ZetaSpacing. Having a const, named constructor makes the intuitive and efficient. + +- Const constructor +- Can wrap any Widget. +- Padding inset around widget. + +
+ +### ZetaSpacing() widget. + +```dart +const ZetaSpacing( + Text('Example'), + size: Dimensions.x1, + type: ZetaSpacingType.square, +), +const ZetaSpacing( + Text('Example'), + size: Dimensions.x1, + type: ZetaSpacingType.squish, +), +const ZetaSpacing( + Text('Example'), + size: Dimensions.x1, + type: ZetaSpacingType.stack, +), +const ZetaSpacing( + Text('Example'), + size: Dimensions.x1, + type: ZetaSpacingType.inline, +), +``` + +This method is less intuitive than using the named constructor, although it does still provide a const constructor for efficiency. + +- Having a const constructor makes this a preferred approach to spacing. +- Can wrap any Widget. +- Padding inset around widget. + +
+ +### SpacingSize extension on double. + +```dart +Container( + padding: Dimensions.x1.square, + margin: Dimensions.x10.squish, + child: Text('Example'), +), +Container( + padding: Dimensions.x1.stack, + margin: Dimensions.x10.inline, + child: Text('Example'), +), +``` + +- Should be used with defined sizes: x0, x1,... or xxs, xs,... (although can be used on any double). +- Can be used for either padding or margin. +- Can be wrapped around any Widget, or used as a parameter. + +
+ +### SpacingWidget extension on Widget. + +```dart +Text('Example').square(Dimensions.x1), +Text('Example').squish(Dimensions.x1), +Text('Example').stack(Dimensions.x1), +Text('Example').inline(Dimensions.x1), +Text('Example').inlineStart(Dimensions.x1), +Text('Example').inlineEnd(Dimensions.x1), +``` + +- Should be used with defined sizes: x0, x1,... or xxs, xs,... (although can be used on any double). +- Padding inset around widget. +- Can be applied to any widget. diff --git a/custom_docs/components/Typography/flutter.md b/custom_docs/components/Typography/flutter.md new file mode 100644 index 00000000..3bd74554 --- /dev/null +++ b/custom_docs/components/Typography/flutter.md @@ -0,0 +1,98 @@ +## ZetaText Usage + +To import ZetaText into a Dart file: + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; +``` + +### Example + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ZetaTextExample extends StatelessWidget{ + const ZetaTextExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ZetaText(...); + } +} +``` + +### Setup + +To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: + +```dart +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/src/theme/theme.dart'; + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ZetaTheme.zeta, + builder: (context, child) => ..., + ); + } +} +``` + +or + +```dart + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/src/theme/theme.dart'; + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return Theme( + data: ZetaTheme.zeta, + child: CupertinoApp( + builder: (context, child) => ..., + ), + ); + } +} +``` + +### ZetaText + +Zeta text styles are within ZetaTheme.zeta, and so will be automatically applied to many widgets that use the built in text theme. When building components, text should not have any spacing by default, and so it is recommended to use the individual text styles with Text, rather than using ZetaText as this will by default apply a x2 squish padding (top and bottom). + +Zeta Typography styles can be used in multiple ways: + +### ZetaText widget with named constructors + +```dart +const ZetaText.bodySmall('Example'), +const ZetaText.displayLarge('Example'), +``` + +This is the preferred way to display text. Having a const, named constructor with helper parameters makes the intuitive and efficient. Constructors exist for all pre-defined text styles and helper functions exist to support all tokens. + +### ZetaText widget + +```dart +const ZetaText('Example', style: ZetaText.zetaBodySmall) +``` + +This method is less intuitive than using the named constructor, although it does still provide a const constructor for efficiency. Having a const, named constructor with helper functions makes the intuitive and efficient. Constructors exist for all pre-defined text styles and helper parameters exist to support all tokens. + +### ZetaText styles + +```dart +Text('Example', style: ZetaText.zetaBodySmall) +Text('Example', style: Theme.of(context).bodySmall) +``` + +Using the base styles gives the greatest flexibility as styles can be extended or added to where needed, at the expense of following the specifications exactly. As ZetaText.textTheme is within the base app style, we can use context to get the styles. This greatly speed up the process of applying Zeta to a pre-existing application. Using this method means helper parameters (such as caps) can not be used and spacing is not applied. This can be useful in components where spacing should be zero. diff --git a/custom_docs/flutter.template.md b/custom_docs/flutter.template.md new file mode 100644 index 00000000..fbbb098f --- /dev/null +++ b/custom_docs/flutter.template.md @@ -0,0 +1,66 @@ +## ZetaX Usage + +To import ZetaX into a Dart file: + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; +``` + +### Example + +```dart +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ZetaXExample extends StatelessWidget{ + const ZetaXExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ZetaY(...); + } +} +``` + +### Setup + +To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: + +```dart +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/src/theme/theme.dart'; + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ZetaTheme.zeta, + builder: (context, child) => ..., + ); + } +} +``` + +or + +```dart + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/src/theme/theme.dart'; + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return Theme( + data: ZetaTheme.zeta, + child: CupertinoApp( + builder: (context, child) => ..., + ), + ); + } +} +``` diff --git a/example/android/build.gradle b/example/android/build.gradle index 58a8c74b..713d7f6e 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index d403d6cb..f5c285f1 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -20,4 +20,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.12.1 +COCOAPODS: 1.13.0 diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5..00000000 --- a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/example/lib/home.dart b/example/lib/home.dart index b3728c64..ad1381d3 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -4,20 +4,21 @@ import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/grid_example.dart'; import 'package:zeta_example/pages/spacing_example.dart'; import 'package:zeta_example/pages/typography_example.dart'; +import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; class Component { final String name; - final Widget page; + final WidgetBuilder pageBuilder; final List children; - Component(this.name, this.page, [this.children = const []]); + Component(this.name, this.pageBuilder, [this.children = const []]); } final List components = [ - Component(GridExample.name, const GridExample()), - Component(SpacingExample.name, const SpacingExample()), - Component(TypographyExample.name, const TypographyExample()), - Component(ColorExample.name, const ColorExample()), + Component(GridExample.name, (context) => const GridExample()), + Component(SpacingExample.name, (context) => const SpacingExample()), + Component(TypographyExample.name, (context) => const TypographyExample()), + Component(ColorExample.name, (context) => const ColorExample()), ]; class Home extends StatefulWidget { @@ -36,8 +37,8 @@ final GoRouter router = GoRouter( ...components.map( (e) => GoRoute( path: e.name, - builder: (_, __) => e.page, - routes: e.children.map((f) => GoRoute(path: f.name, builder: (_, __) => f.page)).toList(), + builder: (_, __) => e.pageBuilder.call(_), + routes: e.children.map((f) => GoRoute(path: f.name, builder: (_, __) => f.pageBuilder(_))).toList(), ), ) ], @@ -49,24 +50,17 @@ class _HomeState extends State { @override Widget build(BuildContext context) { final items = components..sort((a, b) => a.name.compareTo(b.name)); - - final colors = ZetaColors.of(context); - return Scaffold( - appBar: AppBar( - title: const Text('Zeta'), - backgroundColor: colors.primary, - ), - body: ColoredBox( - color: colors.background, - child: ListView.builder( - itemCount: items.length, - itemBuilder: (context, index) { - return ListTile( - title: ZetaText(items[index].name), - onTap: () => context.go('/${items[index].name}'), - ); - }, - ), + return ExampleScaffold( + name: 'Zeta', + child: ListView.builder( + padding: EdgeInsets.all(Dimensions.s), + itemCount: items.length, + itemBuilder: (context, index) { + return ListTile( + title: ZetaText(items[index].name), + onTap: () => context.go('/${items[index].name}'), + ); + }, ), ); } diff --git a/example/lib/main.dart b/example/lib/main.dart index b742e1db..19c69098 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -9,9 +9,24 @@ class ZetaExample extends StatelessWidget { @override Widget build(BuildContext context) { - return Zeta( - builder: (context, theme, colors) { - return MaterialApp.router(theme: theme, routerConfig: router); + return ZetaProvider( + builder: (context, themeData, themeMode) { + final dark = themeData.colorsDark.toScheme(); + final light = themeData.colorsLight.toScheme(); + return MaterialApp.router( + routerConfig: router, + themeMode: themeMode, + theme: ThemeData( + fontFamily: themeData.fontFamily, + scaffoldBackgroundColor: light.background, + colorScheme: light, + ), + darkTheme: ThemeData( + fontFamily: themeData.fontFamily, + scaffoldBackgroundColor: dark.background, + colorScheme: dark, + ), + ); }, ); } diff --git a/example/lib/pages/color_example.dart b/example/lib/pages/color_example.dart index 633b2519..1093e8bf 100644 --- a/example/lib/pages/color_example.dart +++ b/example/lib/pages/color_example.dart @@ -5,6 +5,7 @@ import '../widgets.dart'; class ColorExample extends StatefulWidget { static const String name = 'Color'; + const ColorExample({super.key}); @override @@ -16,7 +17,8 @@ class _ColorExampleState extends State { @override Widget build(BuildContext context) { - final ZetaColors colors = ZetaColors.of(context); + final zeta = Zeta.of(context); + final colors = zeta.colors; return LayoutBuilder( builder: (context, constraints) { final Map swatches = { @@ -33,29 +35,68 @@ class _ColorExampleState extends State { }; final Map generatedSwatches = { - 'Gen-Blue': colors.blue.zetaColorSwatch, + 'Gen-Blue': ZetaColorSwatch.fromColor( + colors.blue, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Blue': colors.blue, - 'Gen-Green': colors.green.zetaColorSwatch, + 'Gen-Green': ZetaColorSwatch.fromColor( + colors.green, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Green': colors.green, - 'Gen-Red': colors.red.zetaColorSwatch, + 'Gen-Red': ZetaColorSwatch.fromColor( + colors.red, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Red': colors.red, - 'Gen-Orange': colors.orange.zetaColorSwatch, + 'Gen-Orange': ZetaColorSwatch.fromColor( + colors.orange, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Orange': colors.orange, - 'Gen-Purple': colors.purple.zetaColorSwatch, + 'Gen-Purple': ZetaColorSwatch.fromColor( + colors.purple, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Purple': colors.purple, - 'Gen-Yellow': colors.yellow.zetaColorSwatch, + 'Gen-Yellow': ZetaColorSwatch.fromColor( + colors.yellow, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Yellow': colors.yellow, - 'Gen-Teal': colors.teal.zetaColorSwatch, + 'Gen-Teal': ZetaColorSwatch.fromColor( + colors.teal, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Teal': colors.teal, - 'Gen-Pink': colors.pink.zetaColorSwatch, + 'Gen-Pink': ZetaColorSwatch.fromColor( + colors.pink, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Pink': colors.pink, - 'Gen-Grey Warm': colors.warm.zetaColorSwatch, + 'Gen-Grey Warm': ZetaColorSwatch.fromColor( + colors.warm, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Grey Warm': colors.warm, - 'Gen-Grey Cool': colors.cool.zetaColorSwatch, + 'Gen-Grey Cool': ZetaColorSwatch.fromColor( + colors.cool, + brightness: zeta.brightness, + contrast: colors.contrast, + ), 'Grey Cool': colors.cool, }; - final Map bw = {'white': colors.white, 'black': colors.black}; final Map textIcon = { 'textDefault': colors.textDefault, 'textSubtle': colors.textSubtle, @@ -84,12 +125,7 @@ class _ColorExampleState extends State { final Map primaries = { 'primaryColor': colors.primary, - 'primarySelected': colors.primary.selected, - 'primaryHover': colors.primary.hover, - 'primaryText': colors.primary.text, - 'primaryBorder': colors.primary.border, - 'primarySubtle': colors.primary.subtle, - 'primarySurface': colors.primary.surface, + 'secondaryColor': colors.secondary, }; final Map alerts = { @@ -101,108 +137,97 @@ class _ColorExampleState extends State { return ExampleScaffold( name: ColorExample.name, - actions: [ - Center(child: ZetaText('DarkMode', textColor: Colors.white)), - Switch.adaptive( - value: colors.isDarkMode, - onChanged: (isDarkMode) => ZetaColors.setColors(context, colors.copyWith(isDarkMode: isDarkMode)), - ), - const SizedBox(width: Dimensions.l), - const Center(child: ZetaText('AAA ', textColor: Colors.white)), - Switch.adaptive( - value: colors.isAAA, - onChanged: (isAAA) => ZetaColors.setColors(context, colors.copyWith(isAAA: isAAA)), - ), - ], - child: Column( - children: [ - MyRow(children: bw, title: 'Black and white'), - 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: primaries, title: 'Primary colors'), - MyRow(children: alerts, title: 'Alert colors'), - Row(children: [ZetaText.displayMedium('Full color swatches')]).squish(Dimensions.x8), - ...swatches.entries.map( - (value) => Row( - children: List.generate(10, (index) => 100 - (10 * index)) - .map( - (e) => Expanded( - child: Container( - height: constraints.maxWidth / 10, - color: value.value[e], - child: FittedBox( - fit: BoxFit.scaleDown, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - DefaultTextStyle( - style: ZetaText.zetaBodyMedium - .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(), - ), - ), - ElevatedButton( - onPressed: () => setState(() => showGeneratedColors = !showGeneratedColors), - child: const Text('Toggle generated colors').square(Dimensions.s), - ).square(Dimensions.s), - if (showGeneratedColors) - Row(children: [ZetaText.displayMedium('Generated color swatches')]).squish(Dimensions.x8), - if (showGeneratedColors) - ...generatedSwatches.entries.map( + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + 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: primaries, title: 'Primary colors'), + MyRow(children: alerts, title: 'Alert colors'), + Row(children: [ZetaText.displayMedium('Full color swatches')]).squish(Dimensions.x8), + ...swatches.entries.map( (value) => Row( - children: List.generate(11, (index) => 110 - (10 * index)) + children: List.generate(10, (index) => 100 - (10 * index)) .map( (e) => Expanded( child: Container( height: constraints.maxWidth / 10, - color: e == 110 ? colors.surface : value.value[e], - child: e == 110 - ? SizedBox() - : FittedBox( - fit: BoxFit.scaleDown, + color: value.value[e], + child: FittedBox( + fit: BoxFit.scaleDown, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + DefaultTextStyle( + style: ZetaText.zetaBodyMedium + .copyWith(color: calculateTextColor(value.value[e] ?? Colors.white)), child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - DefaultTextStyle( - style: ZetaText.zetaBodyMedium - .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), - ), - ], - ), - ), + Text('${value.key.toLowerCase().replaceAll(' ', '')}-$e'), + Text(value.value[e].toString().replaceAll('Color(0xff', '#').substring(0, 7)), ], ), ), + ], + ), + ), ), ), ) .toList(), ), ), - ], + ElevatedButton( + onPressed: () => setState(() => showGeneratedColors = !showGeneratedColors), + child: const Text('Toggle generated colors').square(Dimensions.s), + ).square(Dimensions.s), + if (showGeneratedColors) + Row(children: [ZetaText.displayMedium('Generated color swatches')]).squish(Dimensions.x8), + if (showGeneratedColors) + ...generatedSwatches.entries.map( + (value) => Row( + children: List.generate(11, (index) => 110 - (10 * index)) + .map( + (e) => Expanded( + child: Container( + height: constraints.maxWidth / 10, + color: e == 110 ? colors.surfacePrimary : value.value[e], + child: e == 110 + ? SizedBox() + : FittedBox( + fit: BoxFit.scaleDown, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + DefaultTextStyle( + style: ZetaText.zetaBodyMedium + .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(), + ), + ), + ], + ), ), ); }, @@ -213,6 +238,7 @@ class _ColorExampleState extends State { class MyRow extends StatelessWidget { final Map children; final String title; + const MyRow({super.key, required this.children, required this.title}); @override @@ -225,16 +251,17 @@ class MyRow extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ZetaText.labelLarge(title, textColor: ZetaColors.of(context).textDefault), + ZetaText.labelLarge(title, textColor: Zeta.of(context).colors.textDefault), Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: children.entries .map( - (e) => Container( + (e) => AnimatedContainer( height: 160, width: 160, color: e.value, + duration: const Duration(milliseconds: 250), child: FittedBox( fit: BoxFit.scaleDown, child: Column( diff --git a/example/lib/pages/grid_example.dart b/example/lib/pages/grid_example.dart index d574f5af..fd10ed3d 100644 --- a/example/lib/pages/grid_example.dart +++ b/example/lib/pages/grid_example.dart @@ -11,6 +11,7 @@ class GridExample extends StatelessWidget { static const List asymmetrical = [11, 10, 9, 8, 7, 5, 4, 3, 2, 1]; const GridExample({super.key}); + @override Widget build(BuildContext context) { final List gridItems = List.generate(20, (index) => GridItem(label: (index + 1).toString())); @@ -78,9 +79,12 @@ class GridExample extends StatelessWidget { return ExampleScaffold( name: name, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [...examples.map(ExampleBuilder.new)], + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [...examples.map(ExampleBuilder.new)], + ), ), ); } @@ -89,16 +93,20 @@ class GridExample extends StatelessWidget { class GridItem extends StatelessWidget { final String label; final double? width; + const GridItem({this.label = '', this.width, super.key}); @override Widget build(BuildContext context) { - final ZetaColors colors = ZetaColors.of(context); + final colors = Zeta.of(context).colors; return Container( height: 80, width: width, - decoration: BoxDecoration(border: Border.all(color: colors.blue.border), color: colors.blue.shade20), - child: ZetaText(label), + decoration: BoxDecoration(border: Border.all(color: colors.blue.border), color: colors.blue.surface), + child: Padding( + padding: const EdgeInsets.only(left: 8), + child: ZetaText.bodyLarge(label, textColor: colors.blue.text), + ), ); } } diff --git a/example/lib/pages/spacing_example.dart b/example/lib/pages/spacing_example.dart index a8cfc223..ca7a82ce 100644 --- a/example/lib/pages/spacing_example.dart +++ b/example/lib/pages/spacing_example.dart @@ -14,11 +14,13 @@ class _TypeEx { final String name; final ZetaSpacingType? value; final String description; + const _TypeEx({required this.name, required this.value, required this.description}); } class SpacingExample extends StatelessWidget { static const String name = 'Spacing'; + const SpacingExample({super.key}); static const List<_SizeEx> _sizes = [ @@ -81,9 +83,13 @@ class SpacingExample extends StatelessWidget { Widget build(BuildContext context) { return ExampleScaffold( name: name, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [..._x.map((e) => e == null ? const Divider() : ExampleBuilder(e))]..removeLast(), + child: ListView.builder( + padding: EdgeInsets.all(Dimensions.s), + itemCount: _x.length, + itemBuilder: (context, index) { + final e = _x[index]; + return e == null ? const Divider() : ExampleBuilder(e); + }, ), ); } @@ -92,6 +98,7 @@ class SpacingExample extends StatelessWidget { class _SpaceExample extends StatelessWidget { final double size; final ZetaSpacingType type; + const _SpaceExample({required this.size, required this.type}); @override @@ -100,7 +107,7 @@ class _SpaceExample extends StatelessWidget { children: [ Expanded( child: ColoredBox( - color: ZetaColors.of(context).blue.shade20, + color: Zeta.of(context).colors.blue.shade20, child: ZetaSpacing(const SpacingItem(), size: size, type: type), ), ), diff --git a/example/lib/pages/theme_color_switch.dart b/example/lib/pages/theme_color_switch.dart new file mode 100644 index 00000000..a2ca12fc --- /dev/null +++ b/example/lib/pages/theme_color_switch.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ZetaThemeColorSwitch extends StatelessWidget { + ZetaThemeColorSwitch({super.key}); + + late final _themes = { + "default": ZetaThemeData(), + "teal": ZetaThemeData( + identifier: 'teal', + primary: ZetaColorBase.teal, + ), + "yellow": ZetaThemeData( + identifier: 'yellow', + primary: ZetaColorBase.yellow, + ), + "red": ZetaThemeData( + identifier: 'red', + primary: ZetaColorBase.red, + ), + "purple": ZetaThemeData( + identifier: 'purple', + primary: ZetaColorBase.purple, + ), + }; + + @override + Widget build(BuildContext context) { + var zeta = Zeta.of(context); + + ZetaColors primary(ZetaThemeData data) { + if (zeta.brightness == Brightness.light) { + return data.colorsLight; + } else { + return data.colorsDark; + } + } + + return DropdownButtonHideUnderline( + child: DropdownButton( + value: zeta.themeData.identifier, + elevation: 0, + isDense: true, + alignment: Alignment.center, + icon: SizedBox(width: 8), + dropdownColor: zeta.colors.borderDisabled, + items: _themes.entries.map((e) { + var zetaColors = primary(_themes[e.key]!); + var color = zetaColors.primary; + return DropdownMenuItem( + value: e.value.identifier, + alignment: Alignment.center, + child: CircleAvatar( + backgroundColor: color.surface, + foregroundColor: color, + child: Icon(Icons.color_lens, color: color), + ), + ); + }).toList(), + onChanged: (value) { + final theme = _themes[value]; + if (theme != null) { + ZetaProvider.of(context).updateThemeData(theme); + } + }, + ), + ); + } +} diff --git a/example/lib/pages/theme_constrast_switch.dart b/example/lib/pages/theme_constrast_switch.dart new file mode 100644 index 00000000..9d36c28f --- /dev/null +++ b/example/lib/pages/theme_constrast_switch.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ZetaThemeContrastSwitch extends StatelessWidget { + ZetaThemeContrastSwitch({super.key}); + + late final _themes = [ + ZetaContrast.aa, + ZetaContrast.aaa, + ]; + + @override + Widget build(BuildContext context) { + var zeta = Zeta.of(context); + + ZetaColors zetaColors(ZetaContrast contrast) { + if (zeta.brightness == Brightness.light) { + return zeta.themeData.apply(contrast: contrast).colorsLight; + } else { + return zeta.themeData.apply(contrast: contrast).colorsDark; + } + } + + return DropdownButtonHideUnderline( + child: DropdownButton( + value: zeta.contrast, + elevation: 0, + isDense: true, + alignment: Alignment.center, + icon: SizedBox(width: 8), + dropdownColor: zeta.colors.borderDisabled, + items: _themes.map((e) { + final colors = zetaColors(e); + return DropdownMenuItem( + value: e, + alignment: Alignment.center, + child: CircleAvatar( + backgroundColor: colors.primary.surface, + foregroundColor: colors.primary, + child: ZetaText.bodyMedium( + e == ZetaContrast.aa ? 'AA' : 'AAA', + textColor: colors.primary, + fontWeight: FontWeight.w700, + ), + ), + ); + }).toList(), + onChanged: (value) { + if (value != null) { + ZetaProvider.of(context).updateContrast(value); + } + }, + ), + ); + } +} diff --git a/example/lib/pages/theme_mode_switch.dart b/example/lib/pages/theme_mode_switch.dart new file mode 100644 index 00000000..392d7e12 --- /dev/null +++ b/example/lib/pages/theme_mode_switch.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ZetaThemeModeSwitch extends StatelessWidget { + ZetaThemeModeSwitch({super.key}); + + late final _themes = [ + ThemeMode.system, + ThemeMode.light, + ThemeMode.dark, + ]; + + @override + Widget build(BuildContext context) { + var zeta = Zeta.of(context); + + ZetaColors zetaColors(ThemeMode mode) { + if ((mode == ThemeMode.system && MediaQuery.of(context).platformBrightness == Brightness.light) || + mode == ThemeMode.light) { + return zeta.themeData.colorsLight; + } else { + return zeta.themeData.colorsDark; + } + } + + return DropdownButtonHideUnderline( + child: DropdownButton( + value: zeta.themeMode, + elevation: 0, + isDense: true, + alignment: Alignment.center, + icon: SizedBox(width: 8), + dropdownColor: zeta.colors.borderDisabled, + items: _themes.map((e) { + final colors = zetaColors(e); + return DropdownMenuItem( + value: e, + alignment: Alignment.center, + child: CircleAvatar( + backgroundColor: colors.primary.surface, + foregroundColor: colors.primary, + child: Icon( + e == ThemeMode.system + ? Icons.system_security_update_good + : e == ThemeMode.light + ? Icons.light_mode + : Icons.dark_mode, + color: colors.primary), + ), + ); + }).toList(), + onChanged: (value) { + if (value != null) { + ZetaProvider.of(context).updateThemeMode(value); + } + }, + ), + ); + } +} diff --git a/example/lib/pages/typography_example.dart b/example/lib/pages/typography_example.dart index 8be0e9b0..0ff46d3b 100644 --- a/example/lib/pages/typography_example.dart +++ b/example/lib/pages/typography_example.dart @@ -105,7 +105,7 @@ class TypographyExample extends StatelessWidget { @override Widget build(BuildContext context) { - final ZetaColors colors = ZetaColors.of(context); + final colors = Zeta.of(context).colors; final tokens = [ const ExampleModel( @@ -167,18 +167,21 @@ class TypographyExample extends StatelessWidget { return ExampleScaffold( name: name, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ZetaText.headingLarge('Text').inline(Dimensions.x10), - ...tokens.map(ExampleBuilder.new), - const Divider().squish(Dimensions.x4), - ZetaText.headingLarge('Universal sizes').inline(Dimensions.x10), - ...universalSizes.map(ExampleBuilder.new), - const Divider().squish(Dimensions.x4), - ZetaText.headingLarge('Dedicated sizes').inline(Dimensions.x10), - ...dedicatedSizes.map(ExampleBuilder.new), - ], + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ZetaText.headingLarge('Text').inline(Dimensions.x10), + ...tokens.map(ExampleBuilder.new), + const Divider().squish(Dimensions.x4), + ZetaText.headingLarge('Universal sizes').inline(Dimensions.x10), + ...universalSizes.map(ExampleBuilder.new), + const Divider().squish(Dimensions.x4), + ZetaText.headingLarge('Dedicated sizes').inline(Dimensions.x10), + ...dedicatedSizes.map(ExampleBuilder.new), + ], + ), ), ); } diff --git a/example/lib/widgets.dart b/example/lib/widgets.dart index ad7b375f..99c8da5d 100644 --- a/example/lib/widgets.dart +++ b/example/lib/widgets.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:zeta_example/pages/theme_color_switch.dart'; +import 'package:zeta_example/pages/theme_constrast_switch.dart'; +import 'package:zeta_example/pages/theme_mode_switch.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; class ExampleModel { @@ -21,6 +24,7 @@ class ExampleModel { class ExampleBuilder extends StatelessWidget { final ExampleModel model; + const ExampleBuilder(this.model, {super.key}); @override @@ -31,7 +35,7 @@ class ExampleBuilder extends StatelessWidget { Container( height: 7, width: 7, - decoration: const BoxDecoration(color: Colors.black, shape: BoxShape.circle), + decoration: BoxDecoration(color: Theme.of(context).colorScheme.onSurface, shape: BoxShape.circle), ).squish(Dimensions.x9).inline(Dimensions.x4), Expanded( child: Column( @@ -66,20 +70,24 @@ class ExampleScaffold extends StatelessWidget { @override Widget build(BuildContext context) { - final ZetaColors colors = ZetaColors.of(context); + var theme = Theme.of(context); + final colors = theme.colorScheme; return Scaffold( - appBar: AppBar(title: Text(name), actions: actions, backgroundColor: colors.primary), + appBar: AppBar( + centerTitle: false, + title: Text(name), + backgroundColor: colors.primary, + foregroundColor: colors.onPrimary, + actions: [ + ...actions, + ZetaThemeModeSwitch(), + ZetaThemeContrastSwitch(), + ZetaThemeColorSwitch(), + ], + ), body: SelectionArea( - child: ColoredBox( - color: colors.background, - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: Dimensions.x1, vertical: Dimensions.x6), - child: child, - ), - ), - ), + child: child, ), ); } @@ -88,11 +96,12 @@ class ExampleScaffold extends StatelessWidget { class CodeExample extends StatelessWidget { final String code; final bool fill; + const CodeExample({required this.code, this.fill = false, super.key}); @override Widget build(BuildContext context) { - final ZetaColors colors = ZetaColors.of(context); + var colors = Zeta.of(context).colors; final widget = Container( color: colors.surfaceDisabled, padding: Dimensions.x4.square, @@ -121,6 +130,7 @@ class CodeExample extends StatelessWidget { class FlutterWordMark extends StatelessWidget { final String text; final EdgeInsets padding; + const FlutterWordMark({ this.text = 'Flutter', this.padding = const EdgeInsets.symmetric(horizontal: Dimensions.x5, vertical: Dimensions.x2), @@ -130,7 +140,7 @@ class FlutterWordMark extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - color: ZetaColors.of(context).borderSubtle, + color: Zeta.of(context).colors.borderSubtle, padding: padding, child: ZetaText(text), ); diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index f632ebd4..0782b5c6 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -20,4 +20,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 -COCOAPODS: 1.12.1 +COCOAPODS: 1.13.0 diff --git a/example/pubspec.lock b/example/pubspec.lock index df99aea4..f4af5a61 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + accessibility_tools: + dependency: transitive + description: + name: accessibility_tools + sha256: "0a16adc8dfa3a7ebd38775135d86443011a65d4ecbb438913e4992b5d29135fe" + url: "https://pub.dev" + source: hosted + version: "1.0.0" async: dependency: transitive description: @@ -100,18 +108,18 @@ packages: dependency: "direct main" description: name: go_router - sha256: bd7e671d26fd39c78cba82070fa34ef1f830b0e7ed1aeebccabc6561302a7ee5 + sha256: "2ccd74480706e0a70a0e0dfa9543dede41bc11d0fe3b146a6ad7b7686f6b4407" url: "https://pub.dev" source: hosted - version: "6.5.9" + version: "11.1.4" google_fonts: dependency: "direct main" description: name: google_fonts - sha256: "2776c66b3e97c6cdd58d1bd3281548b074b64f1fd5c8f82391f7456e38849567" + sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8 url: "https://pub.dev" source: hosted - version: "4.0.5" + version: "6.1.0" http: dependency: transitive description: @@ -128,6 +136,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + inspector: + dependency: transitive + description: + name: inspector + sha256: "40ba0ac1c819c85139bfec9d1e283804581a8985c91f19d00e93212cf29226b1" + url: "https://pub.dev" + source: hosted + version: "2.1.0" json_annotation: dependency: transitive description: @@ -196,10 +212,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" path_provider_foundation: dependency: transitive description: @@ -236,18 +252,18 @@ packages: dependency: transitive description: name: platform - sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 + sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.7" resizable_widget: dependency: transitive description: @@ -337,18 +353,18 @@ packages: dependency: "direct dev" description: name: widgetbook - sha256: e2b6bbec0b7805037cb58937200461d0c19fcfdd50dc21fc3ceb558f2489a710 + sha256: e3e4d710f0348da28209b8ec35617b0a425542a3c61889199dddf2b531b159bb url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.4.1" win32: dependency: transitive description: name: win32 - sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa" + sha256: "7c99c0e1e2fa190b48d25c81ca5e42036d5cac81430ef249027d97b0935c553f" url: "https://pub.dev" source: hosted - version: "5.0.7" + version: "5.1.0" xdg_directories: dependency: transitive description: @@ -363,7 +379,7 @@ packages: path: ".." relative: true source: path - version: "0.0.1+11" + version: "0.1.0+1" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" - flutter: ">=3.7.0" + dart: ">=3.1.0 <4.0.0" + flutter: ">=3.10.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 54a3fc12..f6c712a9 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: dependencies: flutter: sdk: flutter - go_router: ^6.5.5 - google_fonts: ^4.0.3 + go_router: ^11.1.2 + google_fonts: ^6.1.0 zeta_flutter: path: ../ diff --git a/example/test/color_test.dart b/example/test/color_test.dart index fb5009a5..c6788f9f 100644 --- a/example/test/color_test.dart +++ b/example/test/color_test.dart @@ -1,10 +1,12 @@ +import 'dart:ui'; + import 'package:flutter_test/flutter_test.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; void main() { testWidgets('Dark mode value', (tester) async { final ZetaColors light = ZetaColors(); - final ZetaColors dark = ZetaColors(isDarkMode: true); + final ZetaColors dark = ZetaColors(brightness: Brightness.dark); expect(light.primary.shade10, dark.primary.shade100); expect(light.primary.shade20, dark.primary.shade90); @@ -15,10 +17,10 @@ void main() { testWidgets('AAA mode value', (tester) async { final ZetaColors aa = ZetaColors(); - final ZetaColors aaa = ZetaColors(isAAA: true); + final ZetaColors aaa = ZetaColors(brightness: Brightness.dark, contrast: ZetaContrast.aaa); - expect(aa.primary.primary, aa.primary.shade60); - expect(aaa.primary.primary, aaa.primary.shade80); + expect(aa.primary.value, aa.primary.shade60.value); + expect(aaa.primary.value, aaa.primary.shade80.value); }); testWidgets('Scheme generator', (tester) async { diff --git a/example/test/test_components.dart b/example/test/test_components.dart index 8e36ac93..117e5717 100644 --- a/example/test/test_components.dart +++ b/example/test/test_components.dart @@ -11,12 +11,21 @@ class TestWidget extends StatelessWidget { Widget build(BuildContext context) { final size = screenSize ?? const Size(1280, 720); - return Zeta( + return ZetaProvider( builder: (context, theme, __) { return Builder( builder: (context) { return MaterialApp( - theme: theme, + theme: ThemeData( + fontFamily: theme.fontFamily, + colorScheme: theme.colorsLight.toScheme(), + textTheme: ZetaText.textTheme, + ), + darkTheme: ThemeData( + fontFamily: theme.fontFamily, + colorScheme: theme.colorsDark.toScheme(), + textTheme: ZetaText.textTheme, + ), home: Scaffold( body: SizedBox( width: size.width, diff --git a/example/test/typography_test.dart b/example/test/typography_test.dart index c33abdf0..b20074f0 100644 --- a/example/test/typography_test.dart +++ b/example/test/typography_test.dart @@ -1,4 +1,4 @@ -import 'package:flutter/widgets.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:zeta_example/pages/typography_example.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; @@ -28,7 +28,7 @@ void main() { fontSize: 100, fontStyle: FontStyle.italic, fontWeight: FontWeight.w500, - textColor: ZetaColors.of(context).textSubtle, + textColor: Zeta.of(context).colors.textSubtle, textDirection: TextDirection.rtl, first: true, last: true, diff --git a/example/widgetbook/components/color_widgetbook.dart b/example/widgetbook/components/color_widgetbook.dart index 1c70872a..3c4ef757 100644 --- a/example/widgetbook/components/color_widgetbook.dart +++ b/example/widgetbook/components/color_widgetbook.dart @@ -10,25 +10,11 @@ WidgetbookComponent colorWidgetBook() { WidgetbookUseCase( name: 'Colors', builder: (BuildContext context) { - final primary = context.knobs.color(label: 'Primary color', initialValue: ZetaColorBase.blue); - final ZetaColors colors; - if (primary != ZetaColorBase.blue) { - colors = ZetaColors( - isDarkMode: context.knobs.boolean(label: 'Dark mode'), - isAAA: context.knobs.boolean(label: 'AAA compliance'), - primary: ZetaColorSwatch.fromColor(primary), - ); - } else { - colors = ZetaColors( - isDarkMode: context.knobs.boolean(label: 'Dark mode'), - isAAA: context.knobs.boolean(label: 'AAA compliance'), - ); - } + final colors = Zeta.of(context).colors; return LayoutBuilder( builder: (context, constraints) { final Map swatches = { - 'Primary': colors.primary, 'Blue': colors.blue, 'Green': colors.green, 'Red': colors.red, @@ -40,7 +26,6 @@ WidgetbookComponent colorWidgetBook() { 'Grey Warm': colors.warm, 'Grey Cool': colors.cool, }; - final Map bw = {'white': colors.white, 'black': colors.black}; final Map textIcon = { 'textDefault': colors.textDefault, 'textSubtle': colors.textSubtle, @@ -66,15 +51,7 @@ WidgetbookComponent colorWidgetBook() { 'surfaceSelectedHovered': colors.surfaceSelectedHovered, 'surfaceSelected': colors.surfaceSelected, }; - final Map primaries = { - 'primaryColor': colors.primary.primary, - 'primarySelected': colors.primary.selected, - 'primaryHover': colors.primary.hover, - 'primaryText': colors.primary.text, - 'primaryBorder': colors.primary.border, - 'primarySubtle': colors.primary.subtle, - 'primarySurface': colors.primary.surface, - }; + final Map alerts = { 'positive': colors.positive, 'negative': colors.negative, @@ -82,22 +59,18 @@ WidgetbookComponent colorWidgetBook() { 'info': colors.info, }; - return Zeta( - colors: colors, + return ZetaProvider( builder: (context3, _, __) { return Container( padding: const EdgeInsets.symmetric(horizontal: Dimensions.l), - color: colors.background, child: SingleChildScrollView( child: Column( children: [ const SizedBox(height: Dimensions.l), - MyRow(children: bw, title: 'Black and white'), 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: primaries, title: 'Primary colors'), MyRow(children: alerts, title: 'Alert colors'), Row(children: [ZetaText.displayMedium('Full color swatches')]).squish(Dimensions.x8), ...swatches.entries.map( diff --git a/example/widgetbook/components/typography_widgetbook.dart b/example/widgetbook/components/typography_widgetbook.dart index 0d638ff6..d7f5949b 100644 --- a/example/widgetbook/components/typography_widgetbook.dart +++ b/example/widgetbook/components/typography_widgetbook.dart @@ -25,7 +25,7 @@ WidgetbookComponent textWidgetBook() { WidgetbookUseCase( name: 'Universal sizes', builder: (context) => Container( - color: ZetaColors.of(context).background, + color: Theme.of(context).colorScheme.background, padding: const EdgeInsets.all(Dimensions.l), child: ZetaText( exampleText, @@ -53,7 +53,7 @@ WidgetbookComponent textWidgetBook() { WidgetbookUseCase( name: 'Dedicated sizes', builder: (context) => Container( - color: ZetaColors.of(context).background, + color: Theme.of(context).colorScheme.background, padding: const EdgeInsets.all(Dimensions.l), child: ZetaText( exampleText, @@ -74,9 +74,8 @@ class _TextWrapper extends StatelessWidget { @override Widget build(BuildContext context) { - final ZetaColors colors = ZetaColors.of(context); + final colors = Zeta.of(context).colors; return Container( - color: colors.background, padding: const EdgeInsets.all(Dimensions.l), child: ZetaText( context.knobs.string(label: 'Input text', initialValue: exampleText.split(',').first), diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index a41b230a..e1c128e3 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -13,7 +13,7 @@ class HotReload extends StatelessWidget { @override Widget build(BuildContext context) { - return Zeta( + return ZetaProvider( builder: (context, theme, colors) { return Widgetbook.material( directories: [ diff --git a/lib/src/components/grid.dart b/lib/src/components/grid.dart index ddac4c9f..d41cce71 100644 --- a/lib/src/components/grid.dart +++ b/lib/src/components/grid.dart @@ -38,6 +38,19 @@ extension _Spacing on DeviceType { /// Zeta Grid. class ZetaGrid extends StatelessWidget { + /// Constructs a [ZetaGrid]. + const ZetaGrid({ + required this.children, + this.col = tokens.Grid.defaultCols, + this.noGaps = false, + this.asymmetricWeight, + this.hybrid = false, + super.key, + }) : assert( + asymmetricWeight == null || (asymmetricWeight > 0 && asymmetricWeight < tokens.Grid.defaultCols), + 'If defined, asymmetricWeight should be in the range 1-11', + ); + /// Number of columns in grid. Should be an even number between 2 and 16, although values above 12 should be used sparingly. /// /// Defaults to 12. @@ -65,19 +78,6 @@ class ZetaGrid extends StatelessWidget { /// Defaults to false. final bool hybrid; - /// Constructs a [ZetaGrid]. - const ZetaGrid({ - required this.children, - this.col = tokens.Grid.defaultCols, - this.noGaps = false, - this.asymmetricWeight, - this.hybrid = false, - super.key, - }) : assert( - asymmetricWeight == null || (asymmetricWeight > 0 && asymmetricWeight < tokens.Grid.defaultCols), - 'If defined, asymmetricWeight should be in the range 1-11', - ); - /// Util to return the smaller of 2 values. num returnSmaller(num in1, num in2) { return in1 > in2 ? in2 : in1; @@ -147,9 +147,10 @@ class ZetaGrid extends StatelessWidget { @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add(DiagnosticsProperty('hybrid', hybrid)); - properties.add(DoubleProperty('col', col)); - properties.add(DiagnosticsProperty('noGaps', noGaps)); - properties.add(IntProperty('asymmetricWeight', asymmetricWeight)); + properties + ..add(DiagnosticsProperty('hybrid', hybrid)) + ..add(DoubleProperty('col', col)) + ..add(DiagnosticsProperty('noGaps', noGaps)) + ..add(IntProperty('asymmetricWeight', asymmetricWeight)); } } diff --git a/lib/src/components/spacing.dart b/lib/src/components/spacing.dart index 9762c6fc..f58138d6 100644 --- a/lib/src/components/spacing.dart +++ b/lib/src/components/spacing.dart @@ -51,23 +51,6 @@ enum ZetaSpacingType { /// Zeta Spacing widget. class ZetaSpacing extends StatelessWidget { - static const double _mod = 2; - - /// Child to be wrapped with spacing insets. - final Widget child; - - /// [ZetaSpacingType] insets applied to [child]. - /// - /// Defaults to [ZetaSpacingType.square]. - final ZetaSpacingType? type; - - /// Size of insets to be applied around [child]. - /// - /// Should be an even number, and be no larger than [Dimensions.x24]. - /// - /// Defaults to [Dimensions.x0]. - final double size; - /// Constructs [ZetaSpacing]. const ZetaSpacing( this.child, { @@ -115,6 +98,22 @@ class ZetaSpacing extends StatelessWidget { /// /// {@macro zeta-spacing-inline} const ZetaSpacing.inlineEnd(this.child, {this.size = Dimensions.x0, super.key}) : type = ZetaSpacingType.inlineEnd; + static const double _mod = 2; + + /// Child to be wrapped with spacing insets. + final Widget child; + + /// [ZetaSpacingType] insets applied to [child]. + /// + /// Defaults to [ZetaSpacingType.square]. + final ZetaSpacingType? type; + + /// Size of insets to be applied around [child]. + /// + /// Should be an even number, and be no larger than [Dimensions.x24]. + /// + /// Defaults to [Dimensions.x0]. + final double size; @override Widget build(BuildContext context) { @@ -137,8 +136,9 @@ class ZetaSpacing extends StatelessWidget { @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add(EnumProperty('type', type)); - properties.add(DoubleProperty('size', size)); + properties + ..add(EnumProperty('type', type)) + ..add(DoubleProperty('size', size)); } } diff --git a/lib/src/components/text.dart b/lib/src/components/text.dart index 9b49f99f..4132446e 100644 --- a/lib/src/components/text.dart +++ b/lib/src/components/text.dart @@ -13,6 +13,327 @@ import '../tokens.dart' as tokens; /// See also: /// * [Text]. class ZetaText extends StatelessWidget { + /// Constructor for [ZetaText]. + const ZetaText( + this.data, { + this.style, + this.resetHeight = false, + this.textColor, + this.fontSize, + this.maxWidth, + this.fontWeight, + this.fontStyle, + this.upperCase = false, + this.decoration, + this.textDirection = TextDirection.ltr, + this.first = false, + this.last = false, + super.key, + }); + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-body-xs} + ZetaText.bodyXSmall( + this.data, { + this.resetHeight = false, + this.maxWidth, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + super.key, + }) : style = zetaBodyXSmall; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-body-s} + ZetaText.bodySmall( + this.data, { + this.resetHeight = false, + this.maxWidth, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + super.key, + }) : style = zetaBodySmall; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-body-m} + ZetaText.bodyMedium( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaBodyMedium; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-body-l} + ZetaText.bodyLarge( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaBodyLarge; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-label-s} + ZetaText.labelSmall( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + super.key, + this.maxWidth, + }) : style = zetaLabelSmall; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-label-m} + ZetaText.labelMedium( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaLabelMedium; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-label-l} + ZetaText.labelLarge( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaLabelLarge; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-title-s} + ZetaText.titleSmall( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaTitleSmall; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-title-m} + ZetaText.titleMedium( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaTitleMedium; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-title-l} + ZetaText.titleLarge( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaTitleLarge; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-heading-s} + ZetaText.headingSmall( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaHeadingSmall; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-heading-m} + ZetaText.headingMedium( + this.data, { + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.resetHeight = false, + this.maxWidth, + super.key, + }) : style = zetaHeadingMedium; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-heading-l} + ZetaText.headingLarge( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaHeadingLarge; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-display-s} + ZetaText.displaySmall( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaDisplaySmall; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-display-m} + ZetaText.displayMedium( + this.data, { + this.resetHeight = false, + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.maxWidth, + super.key, + }) : style = zetaDisplayMedium; + + /// {@macro zeta-component-text} + /// + /// {@macro zeta-type-display-l} + ZetaText.displayLarge( + this.data, { + this.decoration, + this.fontSize, + this.fontStyle, + this.fontWeight, + this.first = false, + this.last = false, + this.textColor, + this.textDirection = TextDirection.ltr, + this.upperCase = false, + this.resetHeight = false, + this.maxWidth, + super.key, + }) : style = zetaDisplayLarge; static const double _defaultChMultiplier = 66; /// Text styles for Zeta. @@ -37,23 +358,23 @@ class ZetaText extends StatelessWidget { ); /// Builds text theme for app based on an instance of [ZetaColors]. - static TextTheme textThemeBuilder(ZetaColors colors) { + static TextTheme themeWithColor(Color color) { return TextTheme( - displayLarge: zetaDisplayLarge.copyWith(color: colors.textDefault), - displayMedium: zetaDisplayMedium.copyWith(color: colors.textDefault), - displaySmall: zetaDisplaySmall.copyWith(color: colors.textDefault), - headlineLarge: zetaHeadingLarge.copyWith(color: colors.textDefault), - headlineMedium: zetaHeadingMedium.copyWith(color: colors.textDefault), - headlineSmall: zetaHeadingSmall.copyWith(color: colors.textDefault), - titleLarge: zetaTitleLarge.copyWith(color: colors.textDefault), - titleMedium: zetaTitleMedium.copyWith(color: colors.textDefault), - titleSmall: zetaTitleSmall.copyWith(color: colors.textDefault), - bodyLarge: zetaBodyLarge.copyWith(color: colors.textDefault), - bodyMedium: zetaBodyMedium.copyWith(color: colors.textDefault), - bodySmall: zetaBodySmall.copyWith(color: colors.textDefault), - labelLarge: zetaLabelLarge.copyWith(color: colors.textDefault), - labelMedium: zetaLabelMedium.copyWith(color: colors.textDefault), - labelSmall: zetaLabelSmall.copyWith(color: colors.textDefault), + displayLarge: zetaDisplayLarge.copyWith(color: color), + displayMedium: zetaDisplayMedium.copyWith(color: color), + displaySmall: zetaDisplaySmall.copyWith(color: color), + headlineLarge: zetaHeadingLarge.copyWith(color: color), + headlineMedium: zetaHeadingMedium.copyWith(color: color), + headlineSmall: zetaHeadingSmall.copyWith(color: color), + titleLarge: zetaTitleLarge.copyWith(color: color), + titleMedium: zetaTitleMedium.copyWith(color: color), + titleSmall: zetaTitleSmall.copyWith(color: color), + bodyLarge: zetaBodyLarge.copyWith(color: color), + bodyMedium: zetaBodyMedium.copyWith(color: color), + bodySmall: zetaBodySmall.copyWith(color: color), + labelLarge: zetaLabelLarge.copyWith(color: color), + labelMedium: zetaLabelMedium.copyWith(color: color), + labelSmall: zetaLabelSmall.copyWith(color: color), ); } @@ -238,528 +559,207 @@ class ZetaText extends StatelessWidget { fontSize: tokens.Dimensions.x8, fontWeight: FontWeight.w500, height: tokens.Dimensions.x9 / tokens.Dimensions.x8, - ); - - /// {@template zeta-type-display-s} - /// Small display text. - /// - /// Used for landing page intros and sections. - /// - /// See also: - /// * [TextTheme.displaySmall]. - /// {@endtemplate} - static TextStyle zetaDisplaySmall = zetaHeadingSmall; - - /// {@template zeta-type-display-m} - /// Medium display text. - /// - /// Used for landing page intros and sections. - /// - /// See also: - /// * [TextTheme.displayMedium]. - /// {@endtemplate} - static TextStyle zetaDisplayMedium = zetaHeadingMedium; - - /// {@template zeta-type-display-l} - /// Large display text. - /// - /// Used for landing page intros. - /// See also: - /// * [TextTheme.displayLarge]. - /// {@endtemplate} - static TextStyle zetaDisplayLarge = zetaHeadingLarge; - - /// Gets approximate char width based on width of O in IBM Plex Sans - /// - /// Only works for IBM Plex. - static double _ch({double multiplier = _defaultChMultiplier, TextStyle? style}) { - final setStyle = style ?? zetaBodyMedium; - const plexCh = 0.6; - - return multiplier * plexCh * (setStyle.fontSize ?? tokens.Dimensions.x3); - } - - /// The text to be displayed. - /// - /// See also: - /// * [Text.data]. - final String? data; - - /// The style applied to the text. - /// - /// Defaults to [zetaBodyMedium]. - /// - /// See also: - /// * [Text.style]. - final TextStyle? style; - - /// Sets text color. - /// - /// See also: - /// * [TextStyle.color]. - final Color? textColor; - - /// Max width of Text box using [_ch]. Not measured in dp / px. - /// - /// [_ch] approximates width of a character using O as basis, so a maxWidth of 60 theoretically returns a max width containing 60 characters. - /// - /// Only works with 'IBM Plex Sans'. - final double? maxWidth; - - /// Font size override. - /// - /// {@template zeta-text-override} - /// Optional as this should be set using [style]. - /// {@endtemplate} - /// See also: - /// * [TextStyle.fontSize]. - final double? fontSize; - - /// Font weight override. - /// - /// {@macro zeta-text-override} - /// - /// See also: - /// * [TextStyle.fontWeight]. - final FontWeight? fontWeight; - - /// Font style override, used to set text to _italic_. - /// - /// - /// - /// See also: - /// * [TextStyle.fontStyle]. - /// * [FontStyle.italic]. - final FontStyle? fontStyle; - - /// Sets all text to uppercase. - /// - /// See also: - /// * [String.toUpperCase]. - final bool upperCase; + ); - /// Decoration override, used to apply decorations such as underline. + /// {@template zeta-type-display-s} + /// Small display text. /// - /// See also: - /// * [TextDecoration.underline]. - /// * [TextDecoration]. - final TextDecoration? decoration; - - /// Text direction, used to set text to either Left to Right or Right to Left. + /// Used for landing page intros and sections. /// /// See also: - /// * [TextDirection.values]. - final TextDirection textDirection; + /// * [TextTheme.displaySmall]. + /// {@endtemplate} + static TextStyle zetaDisplaySmall = zetaHeadingSmall; - /// Sets padding top to 0. + /// {@template zeta-type-display-m} + /// Medium display text. /// - /// Set to true when this text is first in a list. - final bool first; - - /// Sets padding bottom to 0. + /// Used for landing page intros and sections. /// - /// Set to true when this text is last in a list. - final bool last; + /// See also: + /// * [TextTheme.displayMedium]. + /// {@endtemplate} + static TextStyle zetaDisplayMedium = zetaHeadingMedium; - /// Sets the line height to 1 and spacing to 0. + /// {@template zeta-type-display-l} + /// Large display text. /// - /// Defaults to false. - final bool resetHeight; - - /// Constructor for [ZetaText]. - const ZetaText( - this.data, { - this.style, - this.resetHeight = false, - this.textColor, - this.fontSize, - this.maxWidth, - this.fontWeight, - this.fontStyle, - this.upperCase = false, - this.decoration, - this.textDirection = TextDirection.ltr, - this.first = false, - this.last = false, - super.key, - }); - - EdgeInsets get _padding { - if (resetHeight || (first && last)) return tokens.Dimensions.x0.squish; - - return EdgeInsets.only( - top: first ? tokens.Dimensions.x0 : tokens.Dimensions.x2, - bottom: last ? tokens.Dimensions.x0 : tokens.Dimensions.x2, - ); - } - - double? get _fontSize { - if (fontSize == null) return null; - if (fontSize == tokens.Dimensions.x3_5) { - return tokens.Dimensions.x4 / tokens.Dimensions.x3_5; - } - - return ((fontSize ?? 1) + tokens.Dimensions.x1) / (fontSize ?? 1); - } - - @override - Widget build(BuildContext context) { - TextStyle thisStyle = (style ?? ZetaText.zetaBodyMedium).copyWith( - fontSize: style?.fontSize, - fontWeight: style?.fontWeight, - height: style?.height, - ); - - String data = this.data ?? ''; - final Color color = textColor ?? ZetaColors.of(context).textDefault; - - thisStyle = thisStyle.copyWith( - fontSize: (fontSize ?? thisStyle.fontSize ?? tokens.Typography.defaultTextSize) * - MediaQuery.of(context).textScaleFactor, - height: _fontSize, - fontWeight: fontWeight, - decoration: decoration ?? TextDecoration.none, - fontStyle: fontStyle, - color: color, - fontFamily: Theme.of(context).fontFamily, - ); - - if (resetHeight) thisStyle = thisStyle.copyWith(height: 1); - if (upperCase) data = data.toUpperCase(); - - return Padding( - padding: _padding, - child: maxWidth == null - ? Text(data, style: thisStyle, textDirection: textDirection) - : Align( - alignment: textDirection == TextDirection.rtl ? Alignment.centerRight : Alignment.centerLeft, - child: SizedBox( - width: maxWidth == null ? null : _ch(multiplier: maxWidth ?? 0, style: thisStyle), - child: Text(data, style: thisStyle, textDirection: textDirection), - ), - ), - ); - } + /// Used for landing page intros. + /// See also: + /// * [TextTheme.displayLarge]. + /// {@endtemplate} + static TextStyle zetaDisplayLarge = zetaHeadingLarge; - /// {@macro zeta-component-text} + /// Gets approximate char width based on width of O in IBM Plex Sans /// - /// {@macro zeta-type-body-xs} - ZetaText.bodyXSmall( - this.data, { - this.resetHeight = false, - this.maxWidth, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - super.key, - }) : style = zetaBodyXSmall; + /// Only works for IBM Plex. + static double _ch({double multiplier = _defaultChMultiplier, TextStyle? style}) { + final setStyle = style ?? zetaBodyMedium; + const plexCh = 0.6; - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-body-s} - ZetaText.bodySmall( - this.data, { - this.resetHeight = false, - this.maxWidth, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - super.key, - }) : style = zetaBodySmall; + return multiplier * plexCh * (setStyle.fontSize ?? tokens.Dimensions.x3); + } - /// {@macro zeta-component-text} + /// The text to be displayed. /// - /// {@macro zeta-type-body-m} - ZetaText.bodyMedium( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaBodyMedium; + /// See also: + /// * [Text.data]. + final String? data; - /// {@macro zeta-component-text} + /// The style applied to the text. /// - /// {@macro zeta-type-body-l} - ZetaText.bodyLarge( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaBodyLarge; - - /// {@macro zeta-component-text} + /// Defaults to [zetaBodyMedium]. /// - /// {@macro zeta-type-label-s} - ZetaText.labelSmall( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - super.key, - this.maxWidth, - }) : style = zetaLabelSmall; + /// See also: + /// * [Text.style]. + final TextStyle? style; - /// {@macro zeta-component-text} + /// Sets text color. /// - /// {@macro zeta-type-label-m} - ZetaText.labelMedium( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaLabelMedium; + /// See also: + /// * [TextStyle.color]. + final Color? textColor; - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-label-l} - ZetaText.labelLarge( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaLabelLarge; + /// Max width of Text box using [_ch]. Not measured in dp / px. + /// + /// [_ch] approximates width of a character using O as basis, so a maxWidth of 60 theoretically returns a max width containing 60 characters. + /// + /// Only works with 'IBM Plex Sans'. + final double? maxWidth; - /// {@macro zeta-component-text} + /// Font size override. /// - /// {@macro zeta-type-title-s} - ZetaText.titleSmall( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaTitleSmall; + /// {@template zeta-text-override} + /// Optional as this should be set using [style]. + /// {@endtemplate} + /// See also: + /// * [TextStyle.fontSize]. + final double? fontSize; - /// {@macro zeta-component-text} + /// Font weight override. /// - /// {@macro zeta-type-title-m} - ZetaText.titleMedium( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaTitleMedium; + /// {@macro zeta-text-override} + /// + /// See also: + /// * [TextStyle.fontWeight]. + final FontWeight? fontWeight; - /// {@macro zeta-component-text} + /// Font style override, used to set text to _italic_. /// - /// {@macro zeta-type-title-l} - ZetaText.titleLarge( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaTitleLarge; + /// + /// + /// See also: + /// * [TextStyle.fontStyle]. + /// * [FontStyle.italic]. + final FontStyle? fontStyle; - /// {@macro zeta-component-text} + /// Sets all text to uppercase. /// - /// {@macro zeta-type-heading-s} - ZetaText.headingSmall( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaHeadingSmall; + /// See also: + /// * [String.toUpperCase]. + final bool upperCase; - /// {@macro zeta-component-text} + /// Decoration override, used to apply decorations such as underline. /// - /// {@macro zeta-type-heading-m} - ZetaText.headingMedium( - this.data, { - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.resetHeight = false, - this.maxWidth, - super.key, - }) : style = zetaHeadingMedium; + /// See also: + /// * [TextDecoration.underline]. + /// * [TextDecoration]. + final TextDecoration? decoration; - /// {@macro zeta-component-text} + /// Text direction, used to set text to either Left to Right or Right to Left. /// - /// {@macro zeta-type-heading-l} - ZetaText.headingLarge( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaHeadingLarge; + /// See also: + /// * [TextDirection.values]. + final TextDirection textDirection; - /// {@macro zeta-component-text} + /// Sets padding top to 0. /// - /// {@macro zeta-type-display-s} - ZetaText.displaySmall( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaDisplaySmall; + /// Set to true when this text is first in a list. + final bool first; - /// {@macro zeta-component-text} + /// Sets padding bottom to 0. /// - /// {@macro zeta-type-display-m} - ZetaText.displayMedium( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaDisplayMedium; + /// Set to true when this text is last in a list. + final bool last; - /// {@macro zeta-component-text} + /// Sets the line height to 1 and spacing to 0. /// - /// {@macro zeta-type-display-l} - ZetaText.displayLarge( - this.data, { - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.resetHeight = false, - this.maxWidth, - super.key, - }) : style = zetaDisplayLarge; + /// Defaults to false. + final bool resetHeight; + + EdgeInsets get _padding { + if (resetHeight || (first && last)) return tokens.Dimensions.x0.squish; + + return EdgeInsets.only( + top: first ? tokens.Dimensions.x0 : tokens.Dimensions.x2, + bottom: last ? tokens.Dimensions.x0 : tokens.Dimensions.x2, + ); + } + + double? get _fontSize { + if (fontSize == null) return null; + if (fontSize == tokens.Dimensions.x3_5) { + return tokens.Dimensions.x4 / tokens.Dimensions.x3_5; + } + + return ((fontSize ?? 1) + tokens.Dimensions.x1) / (fontSize ?? 1); + } + + @override + Widget build(BuildContext context) { + TextStyle thisStyle = (style ?? ZetaText.zetaBodyMedium).copyWith( + fontSize: style?.fontSize, + fontWeight: style?.fontWeight, + height: style?.height, + ); + + String data = this.data ?? ''; + final Color color = textColor ?? Zeta.of(context).colors.textDefault; + + thisStyle = thisStyle.copyWith( + fontSize: (fontSize ?? thisStyle.fontSize ?? tokens.Typography.defaultTextSize) * + MediaQuery.of(context).textScaleFactor, + height: _fontSize, + fontWeight: fontWeight, + decoration: decoration ?? TextDecoration.none, + fontStyle: fontStyle, + color: color, + ); + + if (resetHeight) thisStyle = thisStyle.copyWith(height: 1); + if (upperCase) data = data.toUpperCase(); + + return Padding( + padding: _padding, + child: maxWidth == null + ? Text(data, style: thisStyle, textDirection: textDirection) + : Align( + alignment: textDirection == TextDirection.rtl ? Alignment.centerRight : Alignment.centerLeft, + child: SizedBox( + width: maxWidth == null ? null : _ch(multiplier: maxWidth ?? 0, style: thisStyle), + child: Text(data, style: thisStyle, textDirection: textDirection), + ), + ), + ); + } + @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add(StringProperty('data', data)); - properties.add(DiagnosticsProperty('style', style)); - properties.add(ColorProperty('textColor', textColor)); - properties.add(DoubleProperty('maxWidth', maxWidth)); - properties.add(DoubleProperty('fontSize', fontSize)); - properties.add(DiagnosticsProperty('fontWeight', fontWeight)); - properties.add(EnumProperty('fontStyle', fontStyle)); - properties.add(DiagnosticsProperty('upperCase', upperCase)); - properties.add(DiagnosticsProperty('decoration', decoration)); - properties.add(EnumProperty('textDirection', textDirection)); - properties.add(DiagnosticsProperty('first', first)); - properties.add(DiagnosticsProperty('last', last)); - properties.add(DiagnosticsProperty('resetHeight', resetHeight)); + properties + ..add(StringProperty('data', data)) + ..add(DiagnosticsProperty('style', style)) + ..add(ColorProperty('textColor', textColor)) + ..add(DoubleProperty('maxWidth', maxWidth)) + ..add(DoubleProperty('fontSize', fontSize)) + ..add(DiagnosticsProperty('fontWeight', fontWeight)) + ..add(EnumProperty('fontStyle', fontStyle)) + ..add(DiagnosticsProperty('upperCase', upperCase)) + ..add(DiagnosticsProperty('decoration', decoration)) + ..add(EnumProperty('textDirection', textDirection)) + ..add(DiagnosticsProperty('first', first)) + ..add(DiagnosticsProperty('last', last)) + ..add(DiagnosticsProperty('resetHeight', resetHeight)); } } diff --git a/lib/src/theme/breakpoints.dart b/lib/src/theme/breakpoints.dart index 9c981666..72c26deb 100644 --- a/lib/src/theme/breakpoints.dart +++ b/lib/src/theme/breakpoints.dart @@ -31,20 +31,7 @@ extension BreakpointLocal on BoxConstraints { /// /// Returns based on the constrains locally to the widget, rather than the whole screen. DeviceType get deviceType { - final width = maxWidth; - if (width <= _Breakpoints._mobilePortraitMax) { - return DeviceType.mobilePortrait; - } else if (width <= _Breakpoints._mobileLandscapeMax) { - return DeviceType.mobileLandscape; - } else if (width <= _Breakpoints._tabletMax) { - return DeviceType.tablet; - } else if (width <= _Breakpoints._desktopMax) { - return DeviceType.desktop; - } else if (width <= _Breakpoints._desktopLMax) { - return DeviceType.desktopL; - } else { - return DeviceType.desktopXL; - } + return _resolveDeviceType(maxWidth); } } @@ -54,21 +41,23 @@ extension BreakpointFull on BuildContext { /// /// Returns based on the full size of the screen, so can be inaccurate in certain scenarios. DeviceType get deviceType { - final width = MediaQuery.of(this).size.width; + return _resolveDeviceType(MediaQuery.of(this).size.width); + } +} - if (width <= _Breakpoints._mobilePortraitMax) { - return DeviceType.mobilePortrait; - } else if (width <= _Breakpoints._mobileLandscapeMax) { - return DeviceType.mobileLandscape; - } else if (width <= _Breakpoints._tabletMax) { - return DeviceType.tablet; - } else if (width <= _Breakpoints._desktopMax) { - return DeviceType.desktop; - } else if (width <= _Breakpoints._desktopLMax) { - return DeviceType.desktopL; - } else { - return DeviceType.desktopXL; - } +DeviceType _resolveDeviceType(double width) { + if (width <= _Breakpoints._mobilePortraitMax) { + return DeviceType.mobilePortrait; + } else if (width <= _Breakpoints._mobileLandscapeMax) { + return DeviceType.mobileLandscape; + } else if (width <= _Breakpoints._tabletMax) { + return DeviceType.tablet; + } else if (width <= _Breakpoints._desktopMax) { + return DeviceType.desktop; + } else if (width <= _Breakpoints._desktopLMax) { + return DeviceType.desktopL; + } else { + return DeviceType.desktopXL; } } diff --git a/lib/src/theme/color_extensions.dart b/lib/src/theme/color_extensions.dart new file mode 100644 index 00000000..d34f6635 --- /dev/null +++ b/lib/src/theme/color_extensions.dart @@ -0,0 +1,305 @@ +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'color_swatch.dart'; +import 'colors_base.dart'; +import 'constants.dart'; +import 'contrast.dart'; + +/// Extensions on [Color] to brighten, lighten, darken and blend colors and +/// can get a shade for gradients. +/// +/// Some of the extensions are rewrites of TinyColor's functions +/// https://pub.dev/packages/tinycolor. The TinyColor algorithms have also +/// been modified to use Flutter's HSLColor class instead of the custom one in +/// the TinyColor lib. The functions from TinyColor re-implemented as Color +/// extensions here are [brighten], [lighten] and [darken]. They are used +/// for color calculations in ZetaColorScheme, but also exposed for reuse. +/// +/// Another frequently used extension is [blend] and [blendAlpha] used to blend +/// two colors using alpha as a percentage or as an 8-bit int alpha value. +/// This extension is used to calculate branded surface +/// colors used by ZetaColorScheme's branded surfaces and for automatic dark +/// color schemes from a light scheme. +/// +/// The [getShadeColor] extension is less frequently used and when used, +/// typically used to color makes colors shades for gradient AppBars, with +/// default setting to not change black and white. +extension ZetaColorExtensions on Color { + /// {@macro zeta.color.color_to_swatch} + ZetaColorSwatch get zetaColorSwatch => ZetaColorSwatch.fromColor(this); + + /// Brightens the color with the given integer percentage amount. + /// Defaults to 10%. + Color brighten([int amount = 10]) { + if (amount <= 0) return this; + if (amount > 100) return Colors.white; + final Color color = Color.fromARGB( + alpha, + math.max(0, math.min(255, red - (255 * -(amount / 100)).round())), + math.max(0, math.min(255, green - (255 * -(amount / 100)).round())), + math.max(0, math.min(255, blue - (255 * -(amount / 100)).round())), + ); + return color; + } + + /// Lightens the color with the given integer percentage amount. + /// Defaults to 10%. + Color lighten([int amount = 10]) { + if (amount <= 0) return this; + if (amount > 100) return Colors.white; + // HSLColor returns saturation 1 for black, we want 0 instead to be able + // lighten black color up along the grey scale from black. + final HSLColor hsl = + this == const Color(0xFF000000) ? HSLColor.fromColor(this).withSaturation(0) : HSLColor.fromColor(this); + return hsl.withLightness(math.min(1, math.max(0, hsl.lightness + amount / 100))).toColor(); + } + + /// Darkens the color with the given integer percentage amount. + /// Defaults to 10%. + Color darken([int amount = 10]) { + if (amount <= 0) return this; + if (amount > 100) return Colors.black; + final HSLColor hsl = HSLColor.fromColor(this); + return hsl.withLightness(math.min(1, math.max(0, hsl.lightness - amount / 100))).toColor(); + } + + /// This getter returns appropriate contrast color based on a given color. + /// It will return a color chosen according to the brightness of this color. + /// + /// * The [Color] instance on which this getter is called is used to determine the brightness based on [ThemeData.estimateBrightnessForColor] method. + /// * If the estimated brightness is light, it will return a color [ZetaColorBase.greyCool].shade90. + /// * If the estimated brightness is not light (meaning it's dark), it will return [ZetaColorBase.white]. + Color get onColor => isLight ? ZetaColorBase.greyCool.shade90 : ZetaColorBase.white; + + /// Returns true if the color's brightness is [Brightness.light], else false. + bool get isLight => ThemeData.estimateBrightnessForColor(this) == Brightness.light; + + /// Returns true if the color's brightness is [Brightness.dark], else false. + bool get isDark => ThemeData.estimateBrightnessForColor(this) == Brightness.dark; + + /// Blend in the given input Color with a percentage of alpha. + /// + /// You typically apply this on a background color, light or dark + /// to create a background color with a hint of a color used in a theme. + /// + /// This is a use case of the alphaBlend static function that exists in + /// dart:ui Color. It is used to create the branded surface colors in + /// ZetaColorScheme and to calculate dark scheme colors from light ones, + /// by blending in white color with light scheme color. + /// + /// Defaults to 10% alpha blend of the passed in Color value. + Color blend(Color input, [int amount = 10]) { + // Skip blending for impossible value and return the instance color value. + if (amount <= 0) return this; + // Blend amounts >= 100 results in the input Color. + if (amount >= 100) return input; + return Color.alphaBlend(input.withAlpha(255 * amount ~/ 100), this); + } + + /// Blend in the given input Color with an alpha value. + /// + /// You typically apply this on a background color, light or dark + /// to create a background color with a hint of a color used in a theme. + /// + /// This is a use case of the alphaBlend static function that exists in + /// dart:ui Color. It is used to create the branded surface colors in + /// ZetaColorScheme and to calculate dark scheme colors from light ones, + /// by blending in white color with light scheme color. + /// + /// Defaults to alpha 0x0A alpha blend of the passed in Color value, + /// which is 10% alpha blend. + Color blendAlpha(Color input, [int alpha = 0x0A]) { + // Skip blending for impossible value and return the instance color value. + if (alpha <= 0) return this; + // Blend amounts >= 255 results in the input Color. + if (alpha >= 255) return input; + return Color.alphaBlend(input.withAlpha(alpha), this); + } + + /// The [getShadeColor] extension is used to make a color darker or lighter, + /// the [shadeValue] defines the amount in % that the shade should be changed. + /// + /// It can be used to make a shade of a color to be used in a gradient. + /// By default it makes a color that is 15% lighter. If lighten is false + /// it makes a color that is 15% darker by default. + /// + /// By default it does not affect black and white colors, but + /// if [keepWhite] is set to false, it will darken white color when [lighten] + /// is false and return a grey color. Wise versa for black with [keepBlack] + /// set to false, it will lighten black color, when [lighten] is true and + /// return a grey shade. + /// + /// White cannot be made lighter and black cannot be made + /// darker, the extension just returns white or black for such attempts, with + /// a quick exist from the call. + Color getShadeColor({ + int shadeValue = 15, + bool lighten = true, + bool keepBlack = true, + bool keepWhite = true, + }) { + if (shadeValue <= 0) return this; + int usedShadeValue = shadeValue; + if (usedShadeValue > 100) usedShadeValue = 100; + + // Trying to make black darker, just return black + if (this == Colors.black && !lighten) return this; + // Black is defined to be kept as black. + if (this == Colors.black && keepBlack) return this; + // Make black lighter as lighten was set and we do not keepBlack + if (this == Colors.black) return this.lighten(usedShadeValue); + + // Trying to make white lighter, just return white + if (this == Colors.white && lighten) return this; + // White is defined to be kept as white. + if (this == Colors.white && keepWhite) return this; + // Make white darker as we do not keep white. + if (this == Colors.white) return darken(usedShadeValue); + // We are dealing with some other color than white or black, so we + // make it lighter or darker based on flag and requested shade % + if (lighten) { + return this.lighten(usedShadeValue); + } else { + return darken(usedShadeValue); + } + } + + /// Return uppercase Flutter style hex code string of the color. + String get hexCode { + return value.toRadixString(16).toUpperCase().padLeft(8, '0'); + } + + /// Applies lightness percentage to color. + Color withLightness(double percentage) { + final HSLColor hslColor = HSLColor.fromColor(this); + + return hslColor.withLightness(percentage).toColor(); + } + + /// Gets lightness of color. + double get lightness => HSLColor.fromColor(this).lightness; + + /// Calculates the contrast ratio between the current color and the given color [b]. + /// + /// The contrast ratio is computed based on the relative luminance of the two colors + /// and is useful for ensuring readability and accessibility of text on backgrounds. + /// + /// Returns the computed contrast ratio. + double contrastRatio(Color b) { + final luminanceA = computeLuminance(); + final luminanceB = b.computeLuminance(); + if (luminanceA > luminanceB) { + return (luminanceA + 0.05) / (luminanceB + 0.05); + } + return (luminanceB + 0.05) / (luminanceA + 0.05); + } + + /// Adjusts the color to a specific contrast target. + /// + /// Parameters: + /// - [target] The target contrast for the color adjustment. + /// - [on] The color to compare contrast against. Defaults to [Colors.white]. + /// - [maxIterations] The maximum number of iterations for color adjustment. Defaults to 1000 iterations. + /// - [epsilon] The difference tolerance for the contrast ratio. Defaults to 0.1. + /// + /// Returns: + /// - A new color with adjusted contrast close to the target contrast. + Color adjustContrast({ + required Color on, + required double target, + int maxIterations = 1000, + double epsilon = 0.1, + }) { + int iteration = 0; + Color adjustedColor = this; + double adjustmentValue; + + while (iteration < maxIterations) { + final currentContrast = adjustedColor.contrastRatio(on); + + if (currentContrast == target || (currentContrast - target).abs() < epsilon) { + break; + } + + final hslColor = HSLColor.fromColor(adjustedColor); + adjustmentValue = (currentContrast - target).abs() * 0.02; + + var newLightness = + (currentContrast < target) ? hslColor.lightness - adjustmentValue : hslColor.lightness + adjustmentValue; + + newLightness = newLightness.clamp(0.0, 1.0); + + adjustedColor = hslColor.withLightness(newLightness).toColor(); + iteration++; + } + + return adjustedColor; + } + + /// Generates a color swatch for this color. + /// A color swatch is a map with integer keys indexing to [Color] objects, + /// typically used for design themes. + /// + /// The function has optional parameters: + /// + /// * [primary] (Default = [kZetaSwatchPrimaryIndex]) - The primary color index for the swatch. This number should be a key in the swatch map. + /// * [targetContrasts] (Default = [kZetaSwatchTargetContrasts]) - Map of target contrast values for each color index. + /// * [background] (Default = [ZetaColorBase.white]) - The color used to determine the contrast of the colors in the swatch. Generally, this should be the background color that the color swatch will be displayed on. + /// * [adjustPrimary] (Default = true) - Determines whether to adjust the contrast of the primary color on the background color. Useful in cases the brand color is being used. + /// + /// Returns a Map object. + Map generateSwatch({ + int primary = kZetaSwatchPrimaryIndex, + Map targetContrasts = kZetaSwatchTargetContrasts, + Color background = ZetaColorBase.white, + bool adjustPrimary = true, + }) { + assert( + targetContrasts.containsKey(primary), + 'Primary key not found in targetContrasts.', + ); + + assert( + targetContrasts.values.every((v) => v > 0), + 'All values in targetContrasts should be positive and non-null.', + ); + + final swatch = {}; + + final adjustedPrimary = adjustPrimary + ? adjustContrast( + on: background, + target: targetContrasts[primary]!, + ) + : this; + + swatch[primary] = adjustedPrimary; + + for (final shade in targetContrasts.keys) { + if (shade != primary) { + swatch[shade] = adjustedPrimary.adjustContrast( + on: background, + target: targetContrasts[shade]!, + ); + } + } + + return swatch; + } + + /// Adjusts the current color to meet the specified accessibility standard [standard] when set against the [on] color. + /// + /// By default, the AA accessibility standard is targeted. You can optionally target AAA. + /// AA: The contrast ratio should be at least 4.57:1 + /// AAA: The contrast ratio should be at least 8.33:1 + /// + /// Returns the adjusted color that meets the specified accessibility standard. + /// Adjusts the current color to meet a specified accessibility standard [standard] when set against the [on] color. + Color ensureAccessibility({ + required Color on, + ZetaContrast standard = ZetaContrast.aa, + }) { + return adjustContrast(on: on, target: standard.targetContrast); + } +} diff --git a/lib/src/theme/color_scheme.dart b/lib/src/theme/color_scheme.dart new file mode 100644 index 00000000..c8cebf6a --- /dev/null +++ b/lib/src/theme/color_scheme.dart @@ -0,0 +1,171 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import 'colors.dart'; +import 'constants.dart'; + +/// Easily craft stunning Flutter themes using pre-set color patterns or your own +/// choices. +/// +/// While Flutter's [ThemeData.from] offers a starting point for [ColorScheme]-based +/// themes, it sometimes defaults to the standard [ThemeData] factory, leading to inconsistencies, +/// particularly in dark themes. [ZetaColorScheme] addresses this by ensuring a seamless theme creation +/// with the [ColorScheme] approach. +/// +/// Themes can be formed using a default [ColorScheme], or by inputting select color values. If both a +/// [ColorScheme] and individual colors are provided, the individual colors will prevail. +/// +/// These factory constructors enable the creation of color-toned themes from a singular color. Additionally, +/// [ZetaColorScheme] simplifies theme crafting with color-branded backgrounds, blending different color degrees, primarily +/// the primary color. +/// +/// Adjusting the themed background of the [AppBar] is straightforward with [ZetaColorScheme], ensuring it aligns with themed colors. +@immutable +class ZetaColorScheme extends ColorScheme with Diagnosticable { + /// Default constructor with no required properties. + /// + /// Creates a light theme by default using the M2 colors as its default + /// theme. + const ZetaColorScheme({ + required this.zetaColors, + + /// If null, defaults to [kZetaFontFamily]; + this.fontFamily = kZetaFontFamily, + required super.brightness, + required super.background, + required super.error, + required super.onBackground, + required super.onError, + required super.onPrimary, + required super.onSecondary, + required super.onSurface, + required super.primary, + required super.secondary, + required super.surface, + super.errorContainer, + super.inversePrimary, + super.inverseSurface, + super.onErrorContainer, + super.onInverseSurface, + super.onPrimaryContainer, + super.onSecondaryContainer, + super.onSurfaceVariant, + super.onTertiary, + super.onTertiaryContainer, + super.outline, + super.outlineVariant, + super.primaryContainer, + super.scrim, + super.secondaryContainer, + super.shadow, + super.surfaceTint, + super.surfaceVariant, + super.tertiary, + super.tertiaryContainer, + }); + + /// Current instance of the [ZetaColors] + final ZetaColors zetaColors; + + /// Name of the font family to use as default font for the text theme in + /// created theme. + /// + /// Same feature as in [ThemeData] factory. Used to apply the font family + /// name to default text theme and primary text theme, also passed along + /// to [ThemeData], + final String? fontFamily; + + /// Creates the copy of the current scheme from the provided values. + @override + ZetaColorScheme copyWith({ + ZetaColors? zetaColors, + String? fontFamily, + Brightness? brightness, + Color? primary, + Color? onPrimary, + Color? primaryContainer, + Color? onPrimaryContainer, + Color? secondary, + Color? onSecondary, + Color? secondaryContainer, + Color? onSecondaryContainer, + Color? tertiary, + Color? onTertiary, + Color? tertiaryContainer, + Color? onTertiaryContainer, + Color? error, + Color? onError, + Color? errorContainer, + Color? onErrorContainer, + Color? background, + Color? onBackground, + Color? surface, + Color? onSurface, + Color? surfaceVariant, + Color? onSurfaceVariant, + Color? outline, + Color? outlineVariant, + Color? shadow, + Color? scrim, + Color? inverseSurface, + Color? onInverseSurface, + Color? inversePrimary, + Color? surfaceTint, + }) { + return ZetaColorScheme( + zetaColors: zetaColors ?? this.zetaColors, + fontFamily: fontFamily ?? this.fontFamily, + brightness: brightness ?? this.brightness, + primary: primary ?? this.primary, + onPrimary: onPrimary ?? this.onPrimary, + primaryContainer: primaryContainer ?? this.primaryContainer, + onPrimaryContainer: onPrimaryContainer ?? this.onPrimaryContainer, + secondary: secondary ?? this.secondary, + onSecondary: onSecondary ?? this.onSecondary, + secondaryContainer: secondaryContainer ?? this.secondaryContainer, + onSecondaryContainer: onSecondaryContainer ?? this.onSecondaryContainer, + tertiary: tertiary ?? this.tertiary, + onTertiary: onTertiary ?? this.onTertiary, + tertiaryContainer: tertiaryContainer ?? this.tertiaryContainer, + onTertiaryContainer: onTertiaryContainer ?? this.onTertiaryContainer, + error: error ?? this.error, + onError: onError ?? this.onError, + errorContainer: errorContainer ?? this.errorContainer, + onErrorContainer: onErrorContainer ?? this.onErrorContainer, + background: background ?? this.background, + onBackground: onBackground ?? this.onBackground, + surface: surface ?? this.surface, + onSurface: onSurface ?? this.onSurface, + surfaceVariant: surfaceVariant ?? this.surfaceVariant, + onSurfaceVariant: onSurfaceVariant ?? this.onSurfaceVariant, + outline: outline ?? this.outline, + outlineVariant: outlineVariant ?? this.outlineVariant, + shadow: shadow ?? this.shadow, + scrim: scrim ?? this.scrim, + inverseSurface: inverseSurface ?? this.inverseSurface, + onInverseSurface: onInverseSurface ?? this.onInverseSurface, + inversePrimary: inversePrimary ?? this.inversePrimary, + surfaceTint: surfaceTint ?? this.surfaceTint, + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('zetaColors', zetaColors)) + ..add(StringProperty('fontFamily', fontFamily)); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + super == other && + other is ZetaColorScheme && + runtimeType == other.runtimeType && + zetaColors == other.zetaColors && + fontFamily == other.fontFamily; + + @override + int get hashCode => super.hashCode ^ zetaColors.hashCode ^ fontFamily.hashCode; +} diff --git a/lib/src/theme/color_swatch.dart b/lib/src/theme/color_swatch.dart new file mode 100644 index 00000000..5b8f8acd --- /dev/null +++ b/lib/src/theme/color_swatch.dart @@ -0,0 +1,197 @@ +import 'package:flutter/material.dart'; + +import 'color_extensions.dart'; +import 'colors_base.dart'; +import 'contrast.dart'; + +/// A swatch of colors with values from 10 (light) to 100 (dark). +@immutable +class ZetaColorSwatch extends ColorSwatch { + /// Constructs a [ZetaColorSwatch]. + /// + /// See also: + /// * [MaterialColor]. + const ZetaColorSwatch({ + this.brightness = Brightness.light, + this.contrast = ZetaContrast.aa, + required int primary, + required Map swatch, + }) : super(primary, swatch); + + /// {@template zeta.color.color_to_swatch} + /// `ZetaColorSwatch` is a color swatch utility to produce different shades + /// of a primary color, following a specific progression of lightness and darkness. + /// + /// This factory constructor creates a color swatch based on a provided primary color. + /// The darker and lighter shades are determined by predefined percentage values. + /// + /// It ensures that the 60th and 80th shades from swatch are abide by the AA and AAA accessibility standards on [background], respectively. + /// [background] color defaults to [ZetaColorBase.greyWarm] shade10. + factory ZetaColorSwatch.fromColor( + Color primary, { + Brightness brightness = Brightness.light, + ZetaContrast contrast = ZetaContrast.aa, + Color background = Colors.white, + }) { + /// Returns a map of colors shades with their respective indexes. + /// Darker shades are obtained by darkening the primary color and + /// lighter shades by lightening it. + /// + /// - 100, 90, 80, and 70 are darker shades of the primary color. + /// - 60 is the primary color itself. + /// - 50, 40, 30, 20, and 10 are progressively lighter shades of the primary color. + return ZetaColorSwatch( + contrast: contrast, + brightness: brightness, + primary: primary.value, + swatch: primary.generateSwatch(background: background), + ).apply(brightness: brightness); + } + + /// Selected contrast level of the system + final Brightness brightness; + + /// Selected contrast level of the system + final ZetaContrast contrast; + + /// This method is an override of the index operator. + /// + /// If the requested index is not in the table (i.e., it results in `null`), the method returns `this`, + /// presumably the default color. + /// + /// [index] The index of the color swatch to return. Must be a non-negative integer. + /// + /// Returns the color at the specified swatch index, or the default color if the index is not in the table. + @override + Color? operator [](int index) => super[brightness == Brightness.dark ? 110 - index : index] ?? this; + + /// The lightest shade. + Color get shade10 => this[10]!; + + /// The second lightest shade. + Color get shade20 => this[20]!; + + /// The third lightest shade. + Color get shade30 => this[30]!; + + /// The fourth lightest shade. + Color get shade40 => this[40]!; + + /// The fifth lightest shade. + Color get shade50 => this[50]!; + + /// The default shade. + Color get shade60 => this[60]!; + + /// The fourth darkest shade. + Color get shade70 => this[70]!; + + /// The third darkest shade. + Color get shade80 => this[80]!; + + /// The second darkest shade. + Color get shade90 => this[90]!; + + /// The darkest shade. + Color get shade100 => this[100]!; + + /// Takes an integer as argument and returns a color shade based on that number. + /// If no shade with the given number exists, it returns the color itself. + /// + /// [number] - The number representing the shade of the color. + /// Returns a color object that represents a specified shade or the color itself. + /// + Color shade(int number) => this[number]!; + + /// Returns the color shade for a surface depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 60. + /// For [ZetaContrast.aaa], it returns 80. + Color get text => shade(contrast.text); + + /// Returns the color shade for an icon depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 60. + /// For [ZetaContrast.aaa], it returns 80. + Color get icon => shade(contrast.icon); + + /// Returns the color shade for a hover state depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 70. + /// For [ZetaContrast.aaa], it returns 90. + Color get hover => shade(contrast.hover); + + /// Returns the color shade for a selected state depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 80. + /// For [ZetaContrast.aaa], it returns 100. + Color get selected => shade(contrast.selected); + + /// Returns the color shade for a focus state depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 80. + /// For [ZetaContrast.aaa], it returns 100. + Color get focus => shade(contrast.focus); + + /// Returns the color shade for a border depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 60. + /// For [ZetaContrast.aaa], it returns 80. + Color get border => shade(contrast.border); + + /// Returns the color shade for a subtle visual element depending on the ZetaContrast value. + /// + /// For both [ZetaContrast.aa] and [ZetaContrast.aaa], it returns 40. + Color get subtle => shade(contrast.subtle); + + /// Returns the color shade for a surface depending on the ZetaContrast value. + /// + /// For both [ZetaContrast.aa] and [ZetaContrast.aaa], it returns 10. + Color get surface => shade(contrast.surface); + + /// Creates a copy of the current [ZetaColorSwatch] with potential modifications + /// based on the provided [contrast] and [brightness]. + /// + /// The [contrast] determines which shade of the color should be used + /// as the primary color in the copied swatch. + /// + /// - [contrast] : The shade to use as the primary color in the new swatch. + /// Defaults to [ZetaContrast.aa]. + /// - [brightness] : The brightness value for the new swatch. + /// Defaults to [Brightness.light]. + ZetaColorSwatch apply({ + ZetaContrast contrast = ZetaContrast.aa, + Brightness brightness = Brightness.light, + }) { + if (this.contrast == contrast && this.brightness == brightness) return this; + + // Generate a list of indices based on brightness level + final indices = List.generate(10, (index) => (index + 1) * 10); + + // Create a new map (swatch) based on the indices and current swatch values + final swatch = Map.fromEntries(indices.map((i) => MapEntry(i, super[i] ?? this))); + + // Determine the primaryIndex color of the new swatch based on the accessibility level + final primaryIndex = brightness == Brightness.light ? contrast.primary : 110 - contrast.primary; + + // Return a new ZetaColorSwatch object with the new primaryIndex color and swatch + return ZetaColorSwatch( + contrast: contrast, + brightness: brightness, + primary: swatch[primaryIndex]!.value, + swatch: swatch, + ); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + super == other && + other is ZetaColorSwatch && + runtimeType == other.runtimeType && + brightness == other.brightness && + contrast == other.contrast; + + @override + int get hashCode => super.hashCode ^ brightness.hashCode ^ contrast.hashCode; +} diff --git a/lib/src/theme/colors.dart b/lib/src/theme/colors.dart index 198d8a22..c54f270f 100644 --- a/lib/src/theme/colors.dart +++ b/lib/src/theme/colors.dart @@ -1,22 +1,199 @@ -import 'dart:math'; - import 'package:flutter/material.dart'; -import '../../../zeta_flutter.dart'; +import 'color_extensions.dart'; +import 'color_scheme.dart'; +import 'color_swatch.dart'; +import 'colors_base.dart'; +import 'contrast.dart'; /// Zeta Colors. /// /// A customizable, token-based color palette, adapting Zeta colors to Flutter's colorScheme. +@immutable class ZetaColors { - /// Sets dark mode to colors. + /// Default constructor for instance of [ZetaColors]. + ZetaColors({ + this.brightness = Brightness.light, + this.contrast = ZetaContrast.aa, + this.link = ZetaColorBase.linkLight, + this.linkVisited = ZetaColorBase.linkVisitedLight, + this.shadow = ZetaColorBase.shadowLight, + this.white = ZetaColorBase.white, + this.black = ZetaColorBase.black, + ZetaColorSwatch? primary, + ZetaColorSwatch? secondary, + ZetaColorSwatch? error, + ZetaColorSwatch? cool, + ZetaColorSwatch? warm, + Color? surfacePrimary, + Color? surfaceSecondary, + Color? surfaceTertiary, + bool adjust = true, + }) : primary = _adjustedValue(primary, ZetaColorBase.blue, adjust, brightness, contrast), + secondary = _adjustedValue(secondary, primary ?? ZetaColorBase.blue, adjust, brightness, contrast), + error = _adjustedValue(error, ZetaColorBase.red, adjust, brightness, contrast), + cool = _adjustedValue(cool, ZetaColorBase.greyCool, adjust, brightness, ZetaContrast.aa), + warm = _adjustedValue(warm, ZetaColorBase.greyWarm, adjust, brightness, ZetaContrast.aa), + blue = _adjustedBase(ZetaColorBase.blue, adjust, brightness, contrast), + green = _adjustedBase(ZetaColorBase.green, adjust, brightness, contrast), + red = _adjustedBase(ZetaColorBase.red, adjust, brightness, contrast), + orange = _adjustedBase(ZetaColorBase.orange, adjust, brightness, contrast), + purple = _adjustedBase(ZetaColorBase.purple, adjust, brightness, contrast), + yellow = _adjustedBase(ZetaColorBase.yellow, adjust, brightness, contrast), + teal = _adjustedBase(ZetaColorBase.teal, adjust, brightness, contrast), + pink = _adjustedBase(ZetaColorBase.pink, adjust, brightness, contrast), + surfacePrimary = surfacePrimary ?? white, + surfaceSecondary = surfaceSecondary ?? + _adjustedValue( + cool, + ZetaColorBase.greyCool, + adjust, + brightness, + ZetaContrast.aa, + ).shade10, + surfaceTertiary = surfaceTertiary ?? + _adjustedValue( + warm, + ZetaColorBase.greyWarm, + adjust, + brightness, + ZetaContrast.aa, + ).shade10; + + /// Factory constructor for a light theme for [ZetaColors]. + /// + /// All color options are nullable and default to a pre-defined contrast color if null. + /// + /// [contrast] The primary contrast color. If not supplied, defaults to [ZetaContrast.aa]. + /// [primary] A color swatch for primary color accent. Defaults to null. + /// [secondary] A color swatch for secondary color accent. Defaults to null. + /// [error] A color swatch for error states. Defaults to null. + /// [cool] A color swatch for cooler color tones. Defaults to null. + /// [warm] A color swatch for warmer color tones. Defaults to null. + /// [white] A color option for white color. Defaults to null. + /// [black] A color option for black color. Defaults to null. + /// [link] A color option for links. Defaults to null. + /// [linkVisited] A color option for visited links. Defaults to null. + /// [shadow] A color option for shadows. Defaults to null. + factory ZetaColors.light({ + ZetaContrast contrast = ZetaContrast.aa, + ZetaColorSwatch? primary, + ZetaColorSwatch? secondary, + ZetaColorSwatch? error, + ZetaColorSwatch? cool, + ZetaColorSwatch? warm, + Color? white, + Color? black, + Color? link, + Color? linkVisited, + Color? shadow, + }) { + return ZetaColors( + white: white ?? ZetaColorBase.white, + black: black ?? ZetaColorBase.black, + cool: cool, + warm: warm, + error: error, + primary: primary, + contrast: contrast, + secondary: secondary, + surfaceTertiary: warm?.shade10, + surfaceSecondary: cool?.shade10, + surfacePrimary: white ?? ZetaColorBase.white, + link: link ?? ZetaColorBase.linkLight, + shadow: shadow ?? ZetaColorBase.shadowLight, + linkVisited: linkVisited ?? ZetaColorBase.linkVisitedLight, + ); + } + + /// Factory constructor for a dark theme for [ZetaColors]. + /// + /// All color options are nullable and default to a pre-defined contrast color if null. + /// + /// [contrast] The primary contrast color. If not supplied, defaults to [ZetaContrast.aa]. + /// [primary] A color swatch for primary color accent. Defaults to null. + /// [secondary] A color swatch for secondary color accent. Defaults to null. + /// [error] A color swatch for error states. Defaults to null. + /// [cool] A color swatch for cooler color tones. Defaults to null. + /// [warm] A color swatch for warmer color tones. Defaults to null. + /// [white] A color option for white color. Defaults to null. + /// [black] A color option for black color. Defaults to null. + /// [link] A color option for links. Defaults to null. + /// [linkVisited] A color option for visited links. Defaults to null. + /// [shadow] A color option for shadows. Defaults to null. + factory ZetaColors.dark({ + ZetaContrast contrast = ZetaContrast.aa, + ZetaColorSwatch? primary, + ZetaColorSwatch? secondary, + ZetaColorSwatch? error, + ZetaColorSwatch? cool, + ZetaColorSwatch? warm, + Color? white, + Color? black, + Color? link, + Color? linkVisited, + Color? shadow, + }) { + return ZetaColors( + cool: cool, + warm: warm, + white: white ?? ZetaColorBase.white, + black: black ?? ZetaColorBase.black, + primary: primary, + contrast: contrast, + secondary: secondary, + error: error, + brightness: Brightness.dark, + surfaceTertiary: warm?.shade10, + surfaceSecondary: cool?.shade10, + surfacePrimary: black ?? ZetaColorBase.black, + link: link ?? ZetaColorBase.linkDark, + shadow: shadow ?? ZetaColorBase.shadowLight, + linkVisited: linkVisited ?? ZetaColorBase.linkVisitedDark, + ); + } + + /// Represents the brightness value. + final Brightness brightness; + + /// Represents the Zeta accessibility standard. + /// {@macro zeta-color-dark} + final ZetaContrast contrast; + + /// Primary color swatch. + /// + /// Defaults to [ZetaColorBase.blue]. + /// + /// {@macro zeta-color-dark} + final ZetaColorSwatch primary; + + /// Secondary color used in app. + /// + /// Defaults to `ZetaColors.cool.90`. + /// + /// Maps to [ColorScheme.secondary]. + final ZetaColorSwatch secondary; + + /// Secondary color used in app. /// - /// If using a default theme, this sets all the parameters needed, otherwise dark colors must be provided. - final bool isDarkMode; + /// Defaults to `ZetaColors.red.60`. + /// + /// Maps to [ColorScheme.error]. + final ZetaColorSwatch error; - /// Sets whether colors should meet AAA requirements for accessability when using built in colors. + /// Cool grey color swatch. + /// + /// Defaults to [ZetaColorBase.greyCool]. /// - /// Typically, when true, default color shade is 80, rather than 60. - final bool isAAA; + /// {@macro zeta-color-dark} + final ZetaColorSwatch cool; + + /// Warm grey color swatch. + /// + /// Defaults to [ZetaColorBase.greyWarm]. + /// + /// {@macro zeta-color-dark} + final ZetaColorSwatch warm; /// Shadow color. /// @@ -25,80 +202,19 @@ class ZetaColors { /// Defaults to #49505E at 10% opacity. final Color shadow; - final Color _linkLight; - final Color _linkVisitedLight; - final Color _linkDark; - final Color _linkVisitedDark; - - final ZetaColorSwatch _primary; - final ZetaColorSwatch _secondary; - final ZetaColorSwatch _cool; - final ZetaColorSwatch _warm; - final ZetaColorSwatch _blue; - final ZetaColorSwatch _green; - final ZetaColorSwatch _red; - final ZetaColorSwatch _orange; - final ZetaColorSwatch _purple; - final ZetaColorSwatch _yellow; - final ZetaColorSwatch _teal; - final ZetaColorSwatch _pink; - - final Color? _background; - final Color? _surface; - final Color? _white; - final Color? _black; - - final Color? _onPrimary; - final Color? _onSecondary; - final Color? _onNegative; - final Color? _onBackground; - final Color? _onSurface; - - final Map _generatedColors; - - static const _minShade = 10; - - /// Generated color for use on [primary]. - /// - /// {@template zeta-color-on-X} - /// If [secondary] is dark, [onSecondary] will be [textDarkMode]. - /// - /// If [secondary] is light, [onSecondary] will be [textLightMode]. - /// {@endtemplate} - Color get onPrimary { - if (_onPrimary != null) return _onPrimary!; - // if (_generatedColors['onPrimary'] != null) return _generatedColors['onPrimary']!; - _generatedColors['onPrimary'] = computeForegroundFromTheme(input: primary); - - return _generatedColors['onPrimary']!; - } - - /// Generated color for use on [secondary]. + /// White color. /// - /// {@macro zeta-color-on-X} - Color get onSecondary { - if (_onSecondary != null) return _onSecondary!; - if (_generatedColors['onSecondary'] != null) return _generatedColors['onSecondary']!; - _generatedColors['onSecondary'] = computeForegroundFromTheme(input: secondary); - - return _generatedColors['onSecondary']!; - } - - /// Generated color for use on [negative]. + /// Maps to [ColorScheme.surface]. /// - /// {@macro zeta-color-on-X} - Color get onNegative { - if (_onNegative != null) return _onNegative!; - if (_generatedColors['onNegative'] != null) return _generatedColors['onNegative']!; - _generatedColors['onNegative'] = computeForegroundFromTheme(input: negative); + /// Defaults to [ZetaColorBase.white]. + final Color white; - return _generatedColors['onNegative']!; - } - - /// On surface color. + /// Shadow color. /// - /// {@macro zeta-color-on-X} - Color get onSurface => _onSurface ?? textDefault; + /// Maps to [ColorScheme.surface]. + /// + /// Defaults to [ZetaColorBase.black]. + final Color black; // Text / icons. @@ -107,7 +223,7 @@ class ZetaColors { /// Defaults to `ZetaColors.cool.90`. /// /// {@template zeta-color-dark} - /// Color swatches are inverted if [ZetaColors.isDarkMode]. + /// Color swatches are inverted if [ZetaColors.brightness] is Dark. /// {@endTemplate} Color get textDefault => cool.shade90; @@ -129,18 +245,52 @@ class ZetaColors { /// Inverse text / icon color. /// - /// Used for text that is not on [ColorScheme.background] or [ColorScheme.surface]. + /// Used for text that is not on [ColorScheme.background] or [ThemeData.scaffoldBackgroundColor]. /// /// Defaults to `ZetaColors.cool.20`. /// /// {@macro zeta-color-dark} Color get textInverse => cool.shade20; + /// Default icon color. + /// + /// Defaults to `ZetaColors.cool.90`. + /// + /// {@template zeta-color-dark} + /// Color swatches are inverted if [ZetaColors.brightness] is Dark. + /// {@endTemplate} + Color get iconDefault => textDefault; + + /// Subtle icon color. + /// + /// Defaults to `ZetaColors.cool.70`. + /// + /// Maps to [ColorScheme.onBackground]. + /// + /// {@macro zeta-color-dark} + Color get iconSubtle => textSubtle; + + /// Disabled icon color. + /// + /// Defaults to `ZetaColors.cool.50`. + /// + /// {@macro zeta-color-dark} + Color get iconDisabled => textDisabled; + + /// Inverse icon color. + /// + /// Used for text that is not on [ColorScheme.background] or [ThemeData.scaffoldBackgroundColor]. + /// + /// Defaults to `ZetaColors.cool.20`. + /// + /// {@macro zeta-color-dark} + Color get iconInverse => textInverse; + // Border variants. /// Default border color. /// - /// Defaults to `ZetaColors.warm.50`. + /// Defaults to `ZetaColors.cool.50`. /// /// {@macro zeta-color-dark} Color get borderDefault => cool.shade50; @@ -166,30 +316,40 @@ class ZetaColors { /// {@macro zeta-color-dark} Color get borderSelected => cool.shade90; + // Links + + /// Link color. + /// + /// Defaults to [ZetaColorBase.linkLight] or [ZetaColorBase.linkDark]. + final Color link; + + /// Link color. + /// + /// Defaults to [ZetaColorBase.linkVisitedLight] or [ZetaColorBase.linkVisitedDark]. + final Color linkVisited; + // Backdrop colors. /// Surface color. /// - /// Maps to [ColorScheme.background]. + /// Maps to [ColorScheme.surface]. /// - /// * Light mode: `ZetaColors.cool.10` + /// * Light mode: `ZetaColors.black` /// * Dark mode: `ZetaColors.white`. - Color get surfacePrimary => isDarkMode ? cool.shade10 : ZetaColorBase.white; + final Color surfacePrimary; - /// Background color. + /// Secondary surface color. /// - /// See [ColorScheme.background]. - Color get background => _background ?? warm.shade10; - - /// On background color. /// - /// See [ColorScheme.onBackground]. - Color get onBackground => _onBackground ?? textSubtle; + /// * `ZetaColors.cool.10`. + final Color surfaceSecondary; - /// Surface color. + /// Tertiary surface color. + /// + /// Maps to [ColorScheme.background] and [ThemeData.scaffoldBackgroundColor] /// - /// See [ColorScheme.surface]. - Color get surface => _surface ?? surfaceSecondary; + /// * `ZetaColors.warm.10`. + final Color surfaceTertiary; /// Disabled surface color. /// @@ -205,634 +365,642 @@ class ZetaColors { /// {@macro zeta-color-dark} Color get surfaceHovered => cool.shade20; - /// Secondary surface color. - /// - /// * Light mode: `ZetaColors.cool.10`. - /// * Dark mode: `ZetaColors.warm.30`. - Color get surfaceSecondary => isDarkMode ? cool.shade10 : white; - - /// Tertiary surface color. - /// - /// Maps to [ColorScheme.background]. - /// - /// * Light mode: `ZetaColors.warm.10`. - /// * Dark mode: `ZetaColors.cool.30`. - Color get surfaceTertiary => isDarkMode ? cool.shade30 : warm.shade10; - /// Selected hover surface color. /// /// Defaults to: `ZetaColors.blue.20`. - Color get surfaceSelectedHovered => blue.shade20; + Color get surfaceSelectedHovered => primary.shade20; /// Selected surface color. /// /// Defaults to: `ZetaColors.blue.10`. - Color get surfaceSelected => blue.shade10; + Color get surfaceSelected => primary.shade10; + + // Alert Colors /// Green positive color. /// - /// Defaults to `ZetaColors.green.60`. + /// Defaults to `ZetaColors.green.60` in AA system. + /// Defaults to `ZetaColors.green.80` in AAA system. /// /// {@macro zeta-color-dark} /// /// {@macro zeta-color-aaa} - Color get positive => green.shade60; + ZetaColorSwatch get positive => green; /// Red negative color. /// - /// Defaults to `ZetaColors.red.60`. + /// Defaults to `ZetaColors.red.60` in AA system. + /// Defaults to `ZetaColors.red.80` in AAA system. /// /// Maps to [ColorScheme.error]. /// /// {@macro zeta-color-dark} /// /// {@macro zeta-color-aaa} - Color get negative => red.shade60; + ZetaColorSwatch get negative => error; /// Orange warning color. /// - /// Defaults to `ZetaColors.orange.60`. + /// Defaults to `ZetaColors.orange.60` in AA system. + /// Defaults to `ZetaColors.orange.80` in AAA system. /// /// {@macro zeta-color-dark} /// /// {@macro zeta-color-aaa} - Color get warning => orange.primary; + ZetaColorSwatch get warning => orange; /// Purple info color. /// - /// Defaults to `ZetaColors.purple.60`. + /// Defaults to `ZetaColors.purple.60` in AA system. + /// Defaults to `ZetaColors.purple.80` in AAA system. /// /// {@macro zeta-color-dark} /// /// {@macro zeta-color-aaa} - Color get info => purple.primary; - - /// Pure white color. - /// - /// `ZetaColors.white`. - Color get white => _white ?? ZetaColorBase.white; - - /// Pure black color. - /// - /// `ZetaColors.black`. - Color get black => _black ?? ZetaColorBase.black; - - /// Link color. - /// - /// Defaults to [ZetaColorBase.linkLight] or [ZetaColorBase.linkDark]. - Color get link => isDarkMode ? _linkDark : _linkLight; - - /// Link color. - /// - /// Defaults to [ZetaColorBase.linkVisitedLight] or [ZetaColorBase.linkVisitedDark]. - Color get linkVisited => isDarkMode ? _linkVisitedDark : _linkVisitedLight; - - /// Static text color for light mode. Does not change based on [isDarkMode]. - /// - /// Defaults to `ZetaColors.cool.90`. - Color get textLightMode => ZetaColorBase.greyCool.shade90; - - /// Static text color for dark mode. Does not change based on [isDarkMode]. - /// - /// Defaults to `ZetaColors.cool.20`. - Color get textDarkMode => ZetaColorBase.greyCool.shade20; - - /// Primary color swatch. - /// - /// Defaults to [ZetaColorBase.blue]. - /// - /// {@macro zeta-color-dark} - ZetaColorSwatch get primary => _primary.copyWith(isDarkMode: isDarkMode, isAAA: isAAA); - - /// Secondary color used in app. - /// - /// Defaults to `ZetaColors.cool.90`. - /// - /// Maps to [ColorScheme.secondary]. - ZetaColorSwatch get secondary => _secondary.copyWith(isDarkMode: isDarkMode, isAAA: isAAA); - - /// Cool grey color swatch. - /// - /// Defaults to [ZetaColorBase.greyCool]. - /// - /// {@macro zeta-color-dark} - ZetaColorSwatch get cool => _cool.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); - - /// Warm grey color swatch. - /// - /// Defaults to [ZetaColorBase.greyWarm]. - /// - /// {@macro zeta-color-dark} - ZetaColorSwatch get warm => _warm.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); + ZetaColorSwatch get info => purple; /// Blue color swatch. /// /// Defaults to [ZetaColorBase.blue]. /// /// {@macro zeta-color-dark} - ZetaColorSwatch get blue => _blue.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); + final ZetaColorSwatch blue; /// Green color swatch. /// /// Defaults to [ZetaColorBase.green]. /// /// {@macro zeta-color-dark} - ZetaColorSwatch get green => _green.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); + final ZetaColorSwatch green; /// Red color swatch. /// /// Defaults to [ZetaColorBase.red]. /// /// {@macro zeta-color-dark} - ZetaColorSwatch get red => _red.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); + final ZetaColorSwatch red; /// Orange color swatch. /// /// Defaults to [ZetaColorBase.orange]. /// /// {@macro zeta-color-dark} - ZetaColorSwatch get orange => _orange.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); + final ZetaColorSwatch orange; /// Purple color swatch. /// /// Defaults to [ZetaColorBase.purple]. /// /// {@macro zeta-color-dark} - ZetaColorSwatch get purple => _purple.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); + final ZetaColorSwatch purple; /// Yellow color swatch. /// /// Defaults to [ZetaColorBase.yellow]. /// /// {@macro zeta-color-dark} - ZetaColorSwatch get yellow => _yellow.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); + final ZetaColorSwatch yellow; /// Teal color swatch. /// /// Defaults to [ZetaColorBase.teal]. /// /// {@macro zeta-color-dark} - ZetaColorSwatch get teal => _teal.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); + final ZetaColorSwatch teal; /// Pink color swatch. /// /// Defaults to [ZetaColorBase.pink]. /// /// {@macro zeta-color-dark} - ZetaColorSwatch get pink => _pink.copyWith(isAAA: isAAA, isDarkMode: isDarkMode); - - /// Generates a [ColorScheme] based on current instance of [ZetaColors]. - /// - /// Colors correspond to the following values: - /// - /// * [ColorScheme.brightness] : [isDarkMode]. - /// * [ColorScheme.primary] : [ZetaColors.primary]. - /// * [ColorScheme.onPrimary] : [onPrimary]. - /// * [ColorScheme.secondary] : [ZetaColors.secondary]. - /// * [ColorScheme.error] : [negative]. - /// * [ColorScheme.onError] : [ZetaColorBase.white]. - /// * [ColorScheme.background] : [surfaceSecondary]. - /// * [ColorScheme.onBackground] : [textSubtle]. - /// * [ColorScheme.surface] : [surfacePrimary]. - /// * [ColorScheme.onSurface] : [textDefault]. - /// * [ColorScheme.shadow] : [shadow]. - ColorScheme get toColorScheme { - return ColorScheme( - brightness: isDarkMode ? Brightness.dark : Brightness.light, - primary: primary.primary, - onPrimary: onPrimary, - secondary: secondary.primary, - onSecondary: onSecondary, - error: negative, - onError: onNegative, - background: background, - onBackground: onBackground, - surface: surface, - onSurface: onSurface, - shadow: shadow, - - // TODO(colors): Consider adding the following colors: - - // errorContainer: - // onErrorContainer: - // inversePrimary: - // inverseSurface: - // onInverseSurface: - // primaryContainer: - // onPrimaryContainer: - // secondaryContainer: - // onSecondaryContainer: - // surfaceVariant: - // onSurfaceVariant: - // tertiary: - // onTertiary: - // tertiaryContainer: - // onTertiaryContainer: - // outline: - // outlineVariant: - // scrim: - // surfaceTint: - ); - } + final ZetaColorSwatch pink; /// Colorful colors. List get rainbow => [red, orange, yellow, green, blue, teal, pink]; - /// Default constructor for instance of [ZetaColors]. - ZetaColors({ - ZetaColorSwatch primary = ZetaColorBase.blue, - ZetaColorSwatch secondary = ZetaColorBase.blue, - ZetaColorSwatch cool = ZetaColorBase.greyCool, - ZetaColorSwatch warm = ZetaColorBase.greyWarm, - ZetaColorSwatch blue = ZetaColorBase.blue, - ZetaColorSwatch green = ZetaColorBase.green, - ZetaColorSwatch red = ZetaColorBase.red, - ZetaColorSwatch orange = ZetaColorBase.orange, - ZetaColorSwatch purple = ZetaColorBase.purple, - ZetaColorSwatch yellow = ZetaColorBase.yellow, - ZetaColorSwatch teal = ZetaColorBase.teal, - ZetaColorSwatch pink = ZetaColorBase.pink, - Color linkLight = ZetaColorBase.linkLight, - Color linkVisitedLight = ZetaColorBase.linkVisitedLight, - Color linkDark = ZetaColorBase.linkDark, - Color linkVisitedDark = ZetaColorBase.linkVisitedDark, - this.shadow = ZetaColorBase.shadow, - this.isDarkMode = false, - this.isAAA = false, - Color? onPrimary, - Color? onSecondary, - Color? onNegative, - Color? background, - Color? onBackground, - Color? surface, - Color? onSurface, - Color? black, - Color? white, - }) : _primary = primary, - _secondary = secondary, - _cool = cool, - _warm = warm, - _blue = blue, - _green = green, - _red = red, - _orange = orange, - _purple = purple, - _yellow = yellow, - _teal = teal, - _pink = pink, - _linkLight = linkLight, - _linkVisitedLight = linkVisitedLight, - _linkDark = linkDark, - _linkVisitedDark = linkVisitedDark, - _onPrimary = onPrimary, - _onSecondary = onSecondary, - _onNegative = onNegative, - _background = background, - _onBackground = onBackground, - _surface = surface, - _onSurface = onSurface, - _black = black, - _white = white, - _generatedColors = {}; - - /// Creates a [ZetaColors] from individual colors and generates their full swatches with [ZetaColorSwatch.fromColor] - ZetaColors.fromColors({ - Color? primary, - Color? secondary, - Color? cool, - Color? warm, - Color? blue, - Color? green, - Color? red, - Color? orange, - Color? purple, - Color? yellow, - Color? teal, - Color? pink, - Color? linkLight, - Color? linkVisitedLight, - Color? linkDark, - Color? linkVisitedDark, - Color? onPrimary, - Color? onSecondary, - Color? onNegative, - Color? background, - Color? onBackground, - Color? surface, - Color? onSurface, - Color? black, - Color? white, - this.shadow = ZetaColorBase.shadow, - this.isDarkMode = false, - this.isAAA = false, - }) : _primary = primary?.zetaColorSwatch ?? ZetaColorBase.blue, - _secondary = secondary?.zetaColorSwatch ?? ZetaColorBase.blue, - _cool = cool?.zetaColorSwatch ?? ZetaColorBase.greyCool, - _warm = warm?.zetaColorSwatch ?? ZetaColorBase.greyWarm, - _blue = blue?.zetaColorSwatch ?? ZetaColorBase.blue, - _green = green?.zetaColorSwatch ?? ZetaColorBase.green, - _red = red?.zetaColorSwatch ?? ZetaColorBase.red, - _orange = orange?.zetaColorSwatch ?? ZetaColorBase.orange, - _purple = purple?.zetaColorSwatch ?? ZetaColorBase.purple, - _yellow = yellow?.zetaColorSwatch ?? ZetaColorBase.yellow, - _teal = teal?.zetaColorSwatch ?? ZetaColorBase.teal, - _pink = pink?.zetaColorSwatch ?? ZetaColorBase.pink, - _linkLight = linkLight ?? ZetaColorBase.linkLight, - _linkVisitedLight = linkVisitedLight ?? ZetaColorBase.linkVisitedLight, - _linkDark = linkDark ?? ZetaColorBase.linkDark, - _linkVisitedDark = linkVisitedDark ?? ZetaColorBase.linkVisitedDark, - _onPrimary = onPrimary, - _onSecondary = onSecondary, - _onNegative = onNegative, - _background = background, - _onBackground = onBackground, - _surface = surface, - _onSurface = onSurface, - _black = black, - _white = white, - _generatedColors = {}; - - /// Returns a new ZetaColors instance, with the copied fields applied. + /// Helper function to adjust color swatch values based on brightness and contrast + static ZetaColorSwatch _adjustedValue( + ZetaColorSwatch? value, + ZetaColorSwatch defaultValue, + bool adjust, + Brightness brightness, + ZetaContrast contrast, + ) { + final swatch = value ?? defaultValue; + return adjust ? swatch.apply(brightness: brightness, contrast: contrast) : swatch; + } + + /// Helper function to adjust color base values based on brightness and contrast + static ZetaColorSwatch _adjustedBase( + ZetaColorSwatch baseColor, + bool adjust, + Brightness brightness, + ZetaContrast contrast, + ) { + return adjust ? baseColor.apply(brightness: brightness, contrast: contrast) : baseColor; + } + + /// Applies new property values to [ZetaColors] and returns a new copy. + /// + /// Each property defaults to the previous value if not specified. ZetaColors copyWith({ - bool? isDarkMode, - bool? isAAA, + Brightness? brightness, + ZetaContrast? contrast, ZetaColorSwatch? primary, ZetaColorSwatch? secondary, + ZetaColorSwatch? error, ZetaColorSwatch? cool, ZetaColorSwatch? warm, - ZetaColorSwatch? blue, - ZetaColorSwatch? green, - ZetaColorSwatch? red, - ZetaColorSwatch? orange, - ZetaColorSwatch? purple, - ZetaColorSwatch? yellow, - ZetaColorSwatch? teal, - ZetaColorSwatch? pink, - Color? linkLight, - Color? linkVisitedLight, - Color? linkDark, - Color? linkVisitedDark, + Color? white, + Color? black, + Color? shadow, + Color? link, + Color? linkVisited, + Color? surfacePrimary, + Color? surfaceSecondary, + Color? surfaceTertiary, }) { return ZetaColors( - primary: primary ?? _primary, + white: white ?? this.white, + black: black ?? this.black, + brightness: brightness ?? this.brightness, + contrast: contrast ?? this.contrast, + primary: primary ?? this.primary, secondary: secondary ?? this.secondary, - cool: cool ?? _cool, - warm: warm ?? _warm, - blue: blue ?? _blue, - green: green ?? _green, - red: red ?? _red, - orange: orange ?? _orange, - purple: purple ?? _purple, - yellow: yellow ?? _yellow, - teal: teal ?? _teal, - pink: pink ?? _pink, - linkLight: linkLight ?? _linkLight, - linkVisitedLight: linkVisitedLight ?? _linkVisitedLight, - linkDark: linkDark ?? _linkDark, - linkVisitedDark: linkVisitedDark ?? _linkVisitedDark, - isDarkMode: isDarkMode ?? this.isDarkMode, - isAAA: isAAA ?? this.isAAA, + error: error ?? this.error, + cool: cool ?? this.cool, + warm: warm ?? this.warm, + shadow: shadow ?? this.shadow, + link: link ?? this.link, + linkVisited: linkVisited ?? this.linkVisited, + surfacePrimary: surfacePrimary ?? this.surfacePrimary, + surfaceSecondary: surfaceSecondary ?? this.surfaceSecondary, + surfaceTertiary: surfaceTertiary ?? this.surfaceTertiary, + adjust: (brightness != null && brightness != this.brightness) || (contrast != null && contrast != this.contrast), ); } - /// Calculates foreground color based on luminance of input. - static Color computeForeground({ - required Color input, - Color light = ZetaColorBase.white, - Color dark = ZetaColorBase.black, - }) => - input.isLight ? dark : light; - - /// Calculates foreground color based on luminance of input. - Color computeForegroundFromTheme({required Color input}) => input.isLight ? textDefault : textInverse; - - /// Setter for updating ZetaColors instance based on current context. - static void setColors(BuildContext context, ZetaColors colors) { - final ZetaState? state = context.findAncestorStateOfType(); - if (state != null) { - state.colors = colors; - } + /// Apply the given contrast to the color scheme and return a new color scheme. + /// + /// If the contrast is the same as the current one, this method will return the current color scheme. + ZetaColors apply({ + required ZetaContrast contrast, + }) { + if (contrast == this.contrast) return this; + return copyWith( + contrast: contrast, + ); } - /// Setter for updating if dark mode is activated for ZetaColors instance based on current context. - static void setDarkMode(BuildContext context, bool val) { - final ZetaState? state = context.findAncestorStateOfType(); - if (state != null) { - state.colors = state.colors.copyWith(isDarkMode: val); - } + /// Returns a [ZetaColorScheme] based on the properties of the current [ZetaColors]. + ZetaColorScheme toScheme() { + final effectivePrimary = primary.shade(contrast.primary); + final effectiveSecondary = secondary.shade(contrast.primary); + final effectiveSurface = surfacePrimary; + final effectiveError = error; + + return ZetaColorScheme( + zetaColors: this, + brightness: brightness, + background: surfaceTertiary, + error: effectiveError, + onBackground: textDefault, + onError: effectiveError.onColor, + onPrimary: effectivePrimary.onColor, + onSecondary: effectiveSecondary.onColor, + onSurface: textDefault, + primary: effectivePrimary, + secondary: effectiveSecondary, + surface: effectiveSurface, + ); } - /// Returns instance of [ZetaColors] from the current context. - /// - /// For this function to work properly, it is required that the current context is beneath a [ZetaColors] widget - /// otherwise a new default instance of [ZetaColors] will be returned. - static ZetaColors of(BuildContext context) { - final ZetaState? state = context.findAncestorStateOfType(); + @override + bool operator ==(Object other) => + identical(this, other) || + other is ZetaColors && + runtimeType == other.runtimeType && + brightness == other.brightness && + contrast == other.contrast && + primary == other.primary && + secondary == other.secondary && + error == other.error && + cool == other.cool && + warm == other.warm && + shadow == other.shadow && + white == other.white && + black == other.black && + link == other.link && + linkVisited == other.linkVisited && + surfacePrimary == other.surfacePrimary && + surfaceSecondary == other.surfaceSecondary && + surfaceTertiary == other.surfaceTertiary && + blue == other.blue && + green == other.green && + red == other.red && + orange == other.orange && + purple == other.purple && + yellow == other.yellow && + teal == other.teal && + pink == other.pink; - // ignore: prefer_const_constructors - return state?.colors ?? ZetaColors(); - } + @override + int get hashCode => + brightness.hashCode ^ + contrast.hashCode ^ + primary.hashCode ^ + secondary.hashCode ^ + error.hashCode ^ + cool.hashCode ^ + warm.hashCode ^ + shadow.hashCode ^ + white.hashCode ^ + black.hashCode ^ + link.hashCode ^ + linkVisited.hashCode ^ + surfacePrimary.hashCode ^ + surfaceSecondary.hashCode ^ + surfaceTertiary.hashCode ^ + blue.hashCode ^ + green.hashCode ^ + red.hashCode ^ + orange.hashCode ^ + purple.hashCode ^ + yellow.hashCode ^ + teal.hashCode ^ + pink.hashCode; } -/// A swatch of colors with values from 10 (light) to 100 (dark). -class ZetaColorSwatch extends ColorSwatch { - /// Returns an element of the swatch table. - @override - Color? operator [](int index) => super[isDarkMode ? (-1 * index) + 110 : index]; +enum _ZetaColorProperties { + primarySwatch, + secondarySwatch, + cool, + warm, + shadow, + textDefault, + textSubtle, + pink, + teal, + yellow, + purple, + orange, + red, + green, + blue, + surfaceSelected, + surfaceSelectedHovered, + surfaceHovered, + surfaceDisabled, + surfaceTertiary, + surfaceSecondary, + surfacePrimary, + linkVisited, + link, + borderSelected, + borderDisabled, + borderSubtle, + borderDefault, + textInverse, + textDisabled, +} - /// True if swatch should be generated for dark mode. +/// Custom extension on ColorScheme which makes [ZetaColors] available through theme context. +/// +/// A customizable, token-based color palette, adapting Zeta colors to Flutter's colorScheme. +extension ZetaColorGetters on ColorScheme { + ZetaColorScheme? get _resolve => this is ZetaColorScheme ? this as ZetaColorScheme : null; + + /// Represents the Zeta accessibility standard. + ZetaContrast get contrast => _resolve?.zetaColors.contrast ?? ZetaContrast.aa; + + /// Primary color swatch. + /// + /// Defaults to [ZetaColorBase.blue]. /// /// {@macro zeta-color-dark} - final bool isDarkMode; + ZetaColorSwatch get primarySwatch => + _resolve?.zetaColors.primary ?? _resolveDefault(_ZetaColorProperties.primarySwatch); - /// True if swatch should be generated for AAA accessability mode. + /// Secondary color used in app. /// - /// {@macro zeta-color-aaa} - final bool isAAA; - - /// The lightest shade. - Color get shade10 => this[10]!; - - /// The second lightest shade. - Color get shade20 => this[20]!; - - /// The third lightest shade. - Color get shade30 => this[30]!; + /// Defaults to `ZetaColors.cool.90`. + /// + /// Maps to [ColorScheme.secondary]. + ZetaColorSwatch get secondarySwatch => + _resolve?.zetaColors.secondary ?? _resolveDefault(_ZetaColorProperties.secondarySwatch); - /// The fourth lightest shade. - Color get shade40 => this[40]!; + /// Cool grey color swatch. + /// + /// Defaults to [ZetaColorBase.greyCool]. + /// + /// {@macro zeta-color-dark} + ZetaColorSwatch get cool => _resolve?.zetaColors.cool ?? _resolveDefault(_ZetaColorProperties.cool); - /// The fifth lightest shade. - Color get shade50 => this[50]!; + /// Warm grey color swatch. + /// + /// Defaults to [ZetaColorBase.greyWarm]. + /// + /// {@macro zeta-color-dark} + ZetaColorSwatch get warm => _resolve?.zetaColors.warm ?? _resolveDefault(_ZetaColorProperties.warm); - /// The default shade. - Color get shade60 => this[60]!; + /// Shadow color. + /// + /// Maps to [ColorScheme.shadow]. + /// + /// Defaults to #49505E at 10% opacity. + Color get shadow => _resolve?.zetaColors.shadow ?? _resolveDefault(_ZetaColorProperties.shadow); - /// The fourth darkest shade. - Color get shade70 => this[70]!; + /// Cool grey color swatch. + /// + /// Defaults to [ZetaColorBase.greyCool]. + /// + /// {@macro zeta-color-dark} + Color get textDefault => _resolve?.zetaColors.textDefault ?? _resolveDefault(_ZetaColorProperties.textDefault); - /// The third darkest shade. - Color get shade80 => this[80]!; + /// Subtle text /icon color. + /// + /// Defaults to `ZetaColors.cool.70`. + /// + /// Maps to [ColorScheme.onBackground]. + /// + /// {@macro zeta-color-dark} + Color get textSubtle => _resolve?.zetaColors.textSubtle ?? _resolveDefault(_ZetaColorProperties.textSubtle); - /// The second darkest shade. - Color get shade90 => this[90]!; + /// Disabled text / icon color. + /// + /// Defaults to `ZetaColors.cool.50`. + /// + /// {@macro zeta-color-dark} + Color get textDisabled => _resolve?.zetaColors.textDisabled ?? _resolveDefault(_ZetaColorProperties.textDisabled); - /// The darkest shade. - Color get shade100 => this[100]!; + /// Inverse text / icon color. + /// + /// Used for text that is not on [ColorScheme.background] or [ThemeData.scaffoldBackgroundColor]. + /// + /// Defaults to `ZetaColors.cool.20`. + /// + /// {@macro zeta-color-dark} + Color get textInverse => _resolve?.zetaColors.textInverse ?? _resolveDefault(_ZetaColorProperties.textInverse); - /// Selected color: 80. - Color get selected => isAAA ? shade100 : shade80; + // Border variants. - /// Hover color: 70. - Color get hover => shade70; + /// Default border color. + /// + /// Defaults to `ZetaColors.warm.50`. + /// + /// {@macro zeta-color-dark} + Color get borderDefault => _resolve?.zetaColors.borderDefault ?? _resolveDefault(_ZetaColorProperties.borderDefault); - /// Text color: 60, or [ZetaColors.textDarkMode] if [isAAA]. + /// Subtle border color. + /// + /// `ZetaColors.cool.40`. /// - /// This color should be used for foreground text when [surface] is the background. - Color get text { - if (isAAA) return isDarkMode ? ZetaColorBase.white : ZetaColorBase.text; + /// {@macro zeta-color-dark} + Color get borderSubtle => _resolve?.zetaColors.borderSubtle ?? _resolveDefault(_ZetaColorProperties.borderSubtle); - return shade60; - } + /// Disabled border color. + /// + /// Defaults to `ZetaColors.cool.30`. + /// + /// {@macro zeta-color-dark} + Color get borderDisabled => + _resolve?.zetaColors.borderDisabled ?? _resolveDefault(_ZetaColorProperties.borderDisabled); - /// Default color for the swatch. + /// Selected border color. /// - /// Defaults to [shade60]. + /// Defaults to `ZetaColors.cool.90`. /// - /// {@macro zeta-color-aaa} - Color get primary => isAAA ? shade80 : shade60; + /// {@macro zeta-color-dark} + Color get borderSelected => + _resolve?.zetaColors.borderSelected ?? _resolveDefault(_ZetaColorProperties.borderSelected); - /// Icon color: 60. + // Links + + /// Link color. /// - /// This color should be used for foreground icons or graphics when [surface] is the background. - Color get icon => shade60; + /// Defaults to [ZetaColorBase.linkLight] or [ZetaColorBase.linkDark]. + Color get link => _resolve?.zetaColors.link ?? _resolveDefault(_ZetaColorProperties.link); - /// Border color: 60. - Color get border => shade60; + /// Link color. + /// + /// Defaults to [ZetaColorBase.linkVisitedLight] or [ZetaColorBase.linkVisitedDark]. + Color get linkVisited => _resolve?.zetaColors.linkVisited ?? _resolveDefault(_ZetaColorProperties.linkVisited); - /// Subtle border color: 40. - Color get borderSubtle => shade40; + // Backdrop colors. - /// Surface color: 10. + /// Surface color. + /// + /// Maps to [ColorScheme.surface]. /// - /// Used for component backgrounds. Use [text] and [icon] for foreground components. - Color get surface => shade10; + /// * Light mode: `ZetaColors.black` + /// * Dark mode: `ZetaColors.white`. + Color get surfacePrimary => + _resolve?.zetaColors.surfacePrimary ?? _resolveDefault(_ZetaColorProperties.surfacePrimary); - /// Returns the subtle color for the swatch. - Color get subtle => shade10; + /// Secondary surface color. + /// + /// + /// * `ZetaColors.cool.10`. + Color get surfaceSecondary => + _resolve?.zetaColors.surfaceSecondary ?? _resolveDefault(_ZetaColorProperties.surfaceSecondary); - /// Generates foreground color to be used on [primary]. - Color get on => ZetaColors.computeForeground(input: primary); + /// Tertiary surface color. + /// + /// Maps to [ColorScheme.background] and [ThemeData.scaffoldBackgroundColor] + /// + /// * `ZetaColors.warm.10`. + Color get surfaceTertiary => + _resolve?.zetaColors.surfaceTertiary ?? _resolveDefault(_ZetaColorProperties.surfaceTertiary); - /// Gets color for disabled mode. - Color get disabled => isDarkMode ? shade30 : shade10; + /// Disabled surface color. + /// + /// Defaults to `ZetaColors.cool.30`. + /// + /// {@macro zeta-color-dark} + Color get surfaceDisabled => + _resolve?.zetaColors.surfaceDisabled ?? _resolveDefault(_ZetaColorProperties.surfaceDisabled); - /// Constructs a [ZetaColorSwatch]. + /// Hover surface color. /// - /// See also: - /// * [MaterialColor]. - const ZetaColorSwatch(super.primary, super._swatch, {this.isDarkMode = false, this.isAAA = false}); + /// Defaults to `ZetaColors.cool.20`. + /// + /// {@macro zeta-color-dark} + Color get surfaceHovered => + _resolve?.zetaColors.surfaceHovered ?? _resolveDefault(_ZetaColorProperties.surfaceHovered); - /// {@template zeta.color.color_to_swatch} - /// Returns a color swatch from a single color. + /// Selected hover surface color. /// - /// This function does NOT guarantee color swatches will meet accessibility criteria AA or AAA. - /// {@endtemplate} - ZetaColorSwatch.fromColor(Color color, {this.isAAA = false, this.isDarkMode = false}) - : super( - color.value, - color._mapFromColor, - ); + /// Defaults to: `ZetaColors.blue.20`. + Color get surfaceSelectedHovered => + _resolve?.zetaColors.surfaceSelectedHovered ?? _resolveDefault(_ZetaColorProperties.surfaceSelectedHovered); - /// Creates a new instance of [ZetaColors] with the fields applied. - ZetaColorSwatch copyWith({bool isDarkMode = false, bool isAAA = false}) { - return ZetaColorSwatch( - isAAA ? shade80.value : shade60.value, - { - for (final v in List.generate(ZetaColors._minShade, (index) => (index + 1) * ZetaColors._minShade)) v: this[v]!, - }, - isDarkMode: isDarkMode, - isAAA: isAAA, - ); - } -} + /// Selected surface color. + /// + /// Defaults to: `ZetaColors.blue.10`. + Color get surfaceSelected => + _resolve?.zetaColors.surfaceSelected ?? _resolveDefault(_ZetaColorProperties.surfaceSelected); -/// Extensions on [Color]. -extension ColorExtension on Color { - /// {@macro zeta.color.color_to_swatch} - ZetaColorSwatch get zetaColorSwatch => ZetaColorSwatch.fromColor(this); + /// Blue color swatch. + /// + /// Defaults to [ZetaColorBase.blue]. + /// + /// {@macro zeta-color-dark} + ZetaColorSwatch get blue => _resolve?.zetaColors.blue ?? _resolveDefault(_ZetaColorProperties.blue); - /// Applies lightness percentage to color. - Color withLightness(double percentage) { - final HSLColor hslColor = HSLColor.fromColor(this); + /// Green color swatch. + /// + /// Defaults to [ZetaColorBase.green]. + /// + /// {@macro zeta-color-dark} + ZetaColorSwatch get green => _resolve?.zetaColors.green ?? _resolveDefault(_ZetaColorProperties.green); - return hslColor.withLightness(percentage).toColor(); - } + /// Red color swatch. + /// + /// Defaults to [ZetaColorBase.red]. + /// + /// {@macro zeta-color-dark} + ZetaColorSwatch get red => _resolve?.zetaColors.red ?? _resolveDefault(_ZetaColorProperties.red); - /// Uses [computeLuminance] to determine if a color if light. - bool get isLight => computeLuminance() > 0.5; + /// Orange color swatch. + /// + /// Defaults to [ZetaColorBase.orange]. + /// + /// {@macro zeta-color-dark} + ZetaColorSwatch get orange => _resolve?.zetaColors.orange ?? _resolveDefault(_ZetaColorProperties.orange); - /// Gets lightness of color. - double get lightness => HSLColor.fromColor(this).lightness; + /// Purple color swatch. + /// + /// Defaults to [ZetaColorBase.purple]. + /// + /// {@macro zeta-color-dark} + ZetaColorSwatch get purple => _resolve?.zetaColors.purple ?? _resolveDefault(_ZetaColorProperties.purple); - /// Calculates the contrast of a color. - double contrast({Color background = Colors.white}) { - final l1 = computeLuminance(); - final l2 = background.computeLuminance(); - const offset = 0.05; + /// Yellow color swatch. + /// + /// Defaults to [ZetaColorBase.yellow]. + /// + /// {@macro zeta-color-dark} + ZetaColorSwatch get yellow => _resolve?.zetaColors.yellow ?? _resolveDefault(_ZetaColorProperties.yellow); - return (max(l1, l2) + offset) / (min(l1, l2) + offset); - } + /// Teal color swatch. + /// + /// Defaults to [ZetaColorBase.teal]. + /// + /// {@macro zeta-color-dark} + ZetaColorSwatch get teal => _resolve?.zetaColors.teal ?? _resolveDefault(_ZetaColorProperties.teal); - /// Rudimentary algorithm to generate a color swatch from a single color. + /// Pink color swatch. /// - /// Attempts to ensure 60 will pass AA against white and 80 will pass AAA against white. - /// This is NOT guaranteed to work. + /// Defaults to [ZetaColorBase.pink]. /// - // TODO(colors): Improve this. - Map get _mapFromColor { - final initialContrast = contrast(); + /// {@macro zeta-color-dark} + ZetaColorSwatch get pink => _resolve?.zetaColors.pink ?? _resolveDefault(_ZetaColorProperties.pink); - double findX(Color c, double minContrast) { - double min = 0; - double max = 1; - bool found = false; - double val; + // Alert Colors - do { - val = (min + max) / 2; + /// Green positive color. + /// + /// Defaults to `ZetaColors.green.60` in AA system. + /// Defaults to `ZetaColors.green.80` in AAA system. + /// + /// {@macro zeta-color-dark} + /// + /// {@macro zeta-color-aaa} + Color get positive => green; - final con = c.withLightness(val).contrast(); + /// Red negative color. + /// + /// Defaults to `ZetaColors.red.60` in AA system. + /// Defaults to `ZetaColors.red.80` in AAA system. + /// + /// Maps to [ColorScheme.error]. + /// + /// {@macro zeta-color-dark} + /// + /// {@macro zeta-color-aaa} + Color get negative => red; - if (con < minContrast) { - max = val; - } else if (con > minContrast + 0.1) { - min = val; - } else { - found = true; - } - } while (!found); + /// Orange warning color. + /// + /// Defaults to `ZetaColors.orange.60` in AA system. + /// Defaults to `ZetaColors.orange.80` in AAA system. + /// + /// {@macro zeta-color-dark} + /// + /// {@macro zeta-color-aaa} + Color get warning => orange; - return val; + /// Purple info color. + /// + /// Defaults to `ZetaColors.purple.60` in AA system. + /// Defaults to `ZetaColors.purple.80` in AAA system. + /// + /// {@macro zeta-color-dark} + /// + /// {@macro zeta-color-aaa} + Color get info => purple; + + T _resolveDefault(_ZetaColorProperties property) { + switch (property) { + case _ZetaColorProperties.primarySwatch: + case _ZetaColorProperties.secondarySwatch: + return ZetaColorBase.blue.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.cool: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.warm: + return ZetaColorBase.greyWarm.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.textDefault: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade90 as T; + case _ZetaColorProperties.textSubtle: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade70 as T; + case _ZetaColorProperties.textInverse: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade20 as T; + case _ZetaColorProperties.textDisabled: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade50 as T; + case _ZetaColorProperties.pink: + return ZetaColorBase.pink.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.teal: + return ZetaColorBase.teal.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.yellow: + return ZetaColorBase.yellow.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.purple: + return ZetaColorBase.purple.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.orange: + return ZetaColorBase.orange.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.red: + return ZetaColorBase.red.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.green: + return ZetaColorBase.green.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.blue: + return ZetaColorBase.blue.apply(brightness: brightness, contrast: contrast) as T; + case _ZetaColorProperties.surfaceSelected: + return ZetaColorBase.blue.apply(brightness: brightness, contrast: contrast).shade10 as T; + case _ZetaColorProperties.surfaceSelectedHovered: + return ZetaColorBase.blue.apply(brightness: brightness, contrast: contrast).shade20 as T; + case _ZetaColorProperties.surfaceHovered: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade20 as T; + case _ZetaColorProperties.surfaceDisabled: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade30 as T; + case _ZetaColorProperties.surfaceTertiary: + return ZetaColorBase.greyWarm.apply(brightness: brightness, contrast: contrast).shade10 as T; + case _ZetaColorProperties.surfaceSecondary: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade10 as T; + case _ZetaColorProperties.borderSelected: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade90 as T; + case _ZetaColorProperties.borderDisabled: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade30 as T; + case _ZetaColorProperties.borderSubtle: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade40 as T; + case _ZetaColorProperties.borderDefault: + return ZetaColorBase.greyCool.apply(brightness: brightness, contrast: contrast).shade50 as T; + case _ZetaColorProperties.shadow: + return (brightness == Brightness.light ? ZetaColorBase.shadowLight : ZetaColorBase.shadowDark) as T; + case _ZetaColorProperties.surfacePrimary: + return (brightness == Brightness.light ? ZetaColorBase.white : ZetaColorBase.black) as T; + case _ZetaColorProperties.linkVisited: + return (brightness == Brightness.light ? ZetaColorBase.linkVisitedLight : ZetaColorBase.linkVisitedDark) as T; + case _ZetaColorProperties.link: + return (brightness == Brightness.light ? ZetaColorBase.linkLight : ZetaColorBase.linkVisitedDark) as T; } - - final double col60 = initialContrast < 4.6 && initialContrast > 4.5 ? lightness : findX(this, 4.5); - final double col80 = findX(this, 7); - - final double darkGap = col80 / 3; - final double lightGap = (1 - col60) / 6; - - return { - 100: withLightness(col80 - (darkGap * 2)), - 90: withLightness(col80 - (darkGap * 1)), - 80: withLightness(col80), - 70: withLightness((col80 + col60) / 2), - 60: withLightness(col60), - 50: withLightness(col60 + (lightGap * 1)), - 40: withLightness(col60 + (lightGap * 2)), - 30: withLightness(col60 + (lightGap * 3)), - 20: withLightness(col60 + (lightGap * 4)), - 10: withLightness(col60 + (lightGap * 5)), - }; } } diff --git a/lib/src/theme/colors_base.dart b/lib/src/theme/colors_base.dart index 36d2a5e6..dbd25a42 100644 --- a/lib/src/theme/colors_base.dart +++ b/lib/src/theme/colors_base.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; -import '../../../zeta_flutter.dart'; +import 'color_swatch.dart'; +import 'colors.dart'; /// Default set of Zeta Colors that can be used to make a [ZetaColors] instance. /// @@ -17,6 +18,8 @@ import '../../../zeta_flutter.dart'; /// * [greyWarm] /// * [greyCool]. class ZetaColorBase { + ZetaColorBase._(); + /// Blue swatch. /// /// {@template zeta-colors-swatch} @@ -25,162 +28,192 @@ class ZetaColorBase { /// See also: /// * [ZetaColorSwatch]. /// {@endtemplate} - static const ZetaColorSwatch blue = ZetaColorSwatch(0xFF0073e6, { - 100: Color(0xFF101B25), - 90: Color(0xFF002C58), - 80: Color(0xFF004D99), - 70: Color(0xFF0061C2), - 60: Color(0xFF0073E6), - 50: Color(0xFF599FE5), - 40: Color(0xFF7EBEFF), - 30: Color(0xFFB7DBFF), - 20: Color(0xFFE2F1FF), - 10: Color(0xFFF1F8FF), - }); + static const ZetaColorSwatch blue = ZetaColorSwatch( + primary: 0xFF0073e6, + swatch: { + 100: Color(0xFF101B25), + 90: Color(0xFF002C58), + 80: Color(0xFF004D99), + 70: Color(0xFF0061C2), + 60: Color(0xFF0073E6), + 50: Color(0xFF599FE5), + 40: Color(0xFF7EBEFF), + 30: Color(0xFFB7DBFF), + 20: Color(0xFFE2F1FF), + 10: Color(0xFFF1F8FF), + }, + ); /// Green swatch. /// /// {@macro zeta-colors-swatch} - static const ZetaColorSwatch green = ZetaColorSwatch(0xFF00864F, { - 100: Color(0xFF081711), - 90: Color(0xFF00331E), - 80: Color(0xFF005F38), - 70: Color(0xFF006D3F), - 60: Color(0xFF00864F), - 50: Color(0xFF67B796), - 40: Color(0xFF84DAB6), - 30: Color(0xFFBEEFDB), - 20: Color(0xFFD8FFEF), - 10: Color(0xFFECFFF7), - }); + static const ZetaColorSwatch green = ZetaColorSwatch( + primary: 0xFF00864F, + swatch: { + 100: Color(0xFF081711), + 90: Color(0xFF00331E), + 80: Color(0xFF005F38), + 70: Color(0xFF006D3F), + 60: Color(0xFF00864F), + 50: Color(0xFF67B796), + 40: Color(0xFF84DAB6), + 30: Color(0xFFBEEFDB), + 20: Color(0xFFD8FFEF), + 10: Color(0xFFECFFF7), + }, + ); /// Red swatch. /// /// {@macro zeta-colors-swatch} - static const ZetaColorSwatch red = ZetaColorSwatch(0xFFD70015, { - 100: Color(0xFF220F11), - 90: Color(0xFF520008), - 80: Color(0xFF8F000E), - 70: Color(0xFFB50012), - 60: Color(0xFFD70015), - 50: Color(0xFFF36170), - 40: Color(0xFFF98C97), - 30: Color(0xFFFFB3BB), - 20: Color(0xFFFFE1E4), - 10: Color(0xFFFFF0F1), - }); + static const ZetaColorSwatch red = ZetaColorSwatch( + primary: 0xFFD70015, + swatch: { + 100: Color(0xFF220F11), + 90: Color(0xFF520008), + 80: Color(0xFF8F000E), + 70: Color(0xFFB50012), + 60: Color(0xFFD70015), + 50: Color(0xFFF36170), + 40: Color(0xFFF98C97), + 30: Color(0xFFFFB3BB), + 20: Color(0xFFFFE1E4), + 10: Color(0xFFFFF0F1), + }, + ); /// Orange swatch. /// /// {@macro zeta-colors-swatch} - static const ZetaColorSwatch orange = ZetaColorSwatch(0xFFC87500, { - 100: Color(0xFF1E1100), - 90: Color(0xFF402600), - 80: Color(0xFF764502), - 70: Color(0xFF965802), - 60: Color(0xFFAE6500), - 50: Color(0xFFD78E26), - 40: Color(0xFFF5A230), - 30: Color(0xFFFFB348), - 20: Color(0xFFFFD292), - 10: Color(0xFFFFE7C6), - }); + static const ZetaColorSwatch orange = ZetaColorSwatch( + primary: 0xFFC87500, + swatch: { + 100: Color(0xFF1E1100), + 90: Color(0xFF402600), + 80: Color(0xFF764502), + 70: Color(0xFF965802), + 60: Color(0xFFAE6500), + 50: Color(0xFFD78E26), + 40: Color(0xFFF5A230), + 30: Color(0xFFFFB348), + 20: Color(0xFFFFD292), + 10: Color(0xFFFFE7C6), + }, + ); /// Purple swatch. /// /// {@macro zeta-colors-swatch} - static const ZetaColorSwatch purple = ZetaColorSwatch(0xFF6400D6, { - 100: Color(0xFF180F22), - 90: Color(0xFF260052), - 80: Color(0xFF43008F), - 70: Color(0xFF6400D6), - 60: Color(0xFF7E0CFF), - 50: Color(0xFF9B71DF), - 40: Color(0xFFCEA4FF), - 30: Color(0xFFDCC1FB), - 20: Color(0xFFEFE1FF), - 10: Color(0xFFF7F0FF), - }); + static const ZetaColorSwatch purple = ZetaColorSwatch( + primary: 0xFF6400D6, + swatch: { + 100: Color(0xFF180F22), + 90: Color(0xFF260052), + 80: Color(0xFF43008F), + 70: Color(0xFF6400D6), + 60: Color(0xFF7E0CFF), + 50: Color(0xFF9B71DF), + 40: Color(0xFFCEA4FF), + 30: Color(0xFFDCC1FB), + 20: Color(0xFFEFE1FF), + 10: Color(0xFFF7F0FF), + }, + ); /// Yellow swatch. /// /// {@macro zeta-colors-swatch} - static const ZetaColorSwatch yellow = ZetaColorSwatch(0xFFA38600, { - 100: Color(0xFF181400), - 90: Color(0xFF352B00), - 80: Color(0xFF564908), - 70: Color(0xFF766200), - 60: Color(0xFF8D7400), - 50: Color(0xFFC2A728), - 40: Color(0xFFDBB91C), - 30: Color(0xFFF3D961), - 20: Color(0xFFFFEA89), - 10: Color(0xFFFFF7D4), - }); + static const ZetaColorSwatch yellow = ZetaColorSwatch( + primary: 0xFFA38600, + swatch: { + 100: Color(0xFF181400), + 90: Color(0xFF352B00), + 80: Color(0xFF564908), + 70: Color(0xFF766200), + 60: Color(0xFF8D7400), + 50: Color(0xFFC2A728), + 40: Color(0xFFDBB91C), + 30: Color(0xFFF3D961), + 20: Color(0xFFFFEA89), + 10: Color(0xFFFFF7D4), + }, + ); /// Teal swatch. /// /// {@macro zeta-colors-swatch} - static const ZetaColorSwatch teal = ZetaColorSwatch(0xFF018786, { - 100: Color(0xFF0A1616), - 90: Color(0xFF003535), - 80: Color(0xFF005B5B), - 70: Color(0xFF017474), - 60: Color(0xFF1A8080), - 50: Color(0xFF65C5C5), - 40: Color(0xFF91E1E1), - 30: Color(0xFFBCFBFB), - 20: Color(0xFFD9FFFF), - 10: Color(0xFFECFFFF), - }); + static const ZetaColorSwatch teal = ZetaColorSwatch( + primary: 0xFF018786, + swatch: { + 100: Color(0xFF0A1616), + 90: Color(0xFF003535), + 80: Color(0xFF005B5B), + 70: Color(0xFF017474), + 60: Color(0xFF1A8080), + 50: Color(0xFF65C5C5), + 40: Color(0xFF91E1E1), + 30: Color(0xFFBCFBFB), + 20: Color(0xFFD9FFFF), + 10: Color(0xFFECFFFF), + }, + ); /// Pink swatch. /// /// {@macro zeta-colors-swatch} - static const ZetaColorSwatch pink = ZetaColorSwatch(0xFFAB006D, { - 100: Color(0xFF2E001E), - 90: Color(0xFF640040), - 80: Color(0xFF840054), - 70: Color(0xFFAB006D), - 60: Color(0xFFD30589), - 50: Color(0xFFEE78C3), - 40: Color(0xFFFF94D8), - 30: Color(0xFFFFBEE7), - 20: Color(0xFFFFE3F5), - 10: Color(0xFFFFF7FC), - }); + static const ZetaColorSwatch pink = ZetaColorSwatch( + primary: 0xFFAB006D, + swatch: { + 100: Color(0xFF2E001E), + 90: Color(0xFF640040), + 80: Color(0xFF840054), + 70: Color(0xFFAB006D), + 60: Color(0xFFD30589), + 50: Color(0xFFEE78C3), + 40: Color(0xFFFF94D8), + 30: Color(0xFFFFBEE7), + 20: Color(0xFFFFE3F5), + 10: Color(0xFFFFF7FC), + }, + ); /// Grey warm swatch. /// /// {@macro zeta-colors-swatch} - static const ZetaColorSwatch greyWarm = ZetaColorSwatch(0xFF858585, { - 100: Color(0xFF151519), - 90: Color(0xFF202020), - 80: Color(0xFF313131), - 70: Color(0xFF585858), - 60: Color(0xFF858585), - 50: Color(0xFFB9B9B9), - 40: Color(0xFFDEDEDE), - 30: Color(0xFFEDEDED), - 20: Color(0xFFF7F7F7), - 10: Color(0xFFFAFAFA), - }); + static const ZetaColorSwatch greyWarm = ZetaColorSwatch( + primary: 0xFF858585, + swatch: { + 100: Color(0xFF151519), + 90: Color(0xFF202020), + 80: Color(0xFF313131), + 70: Color(0xFF585858), + 60: Color(0xFF858585), + 50: Color(0xFFB9B9B9), + 40: Color(0xFFDEDEDE), + 30: Color(0xFFEDEDED), + 20: Color(0xFFF7F7F7), + 10: Color(0xFFFAFAFA), + }, + ); /// Grey cool swatch. /// /// {@macro zeta-colors-swatch} - static const ZetaColorSwatch greyCool = ZetaColorSwatch(0xFF7A8190, { - 100: Color(0xFF0C0D0E), - 90: Color(0xFF1D1E23), - 80: Color(0xFF2C2F36), - 70: Color(0xFF545963), - 60: Color(0xFF7A8190), - 50: Color(0xFF8D95A3), - 40: Color(0xFFCED2DB), - 30: Color(0xFFE0E3E9), - 20: Color(0xFFF3F6FA), - 10: Color(0xFFF8FBFF), - }); + static const ZetaColorSwatch greyCool = ZetaColorSwatch( + primary: 0xFF7A8190, + swatch: { + 100: Color(0xFF0C0D0E), + 90: Color(0xFF1D1E23), + 80: Color(0xFF2C2F36), + 70: Color(0xFF545963), + 60: Color(0xFF7A8190), + 50: Color(0xFF8D95A3), + 40: Color(0xFFCED2DB), + 30: Color(0xFFE0E3E9), + 20: Color(0xFFF3F6FA), + 10: Color(0xFFF8FBFF), + }, + ); /// Pure white. /// @@ -208,5 +241,8 @@ class ZetaColorBase { static const Color linkVisitedDark = Color(0xFF47A3FF); /// Default shadow color. - static const Color shadow = Color(0x1A49505E); + static const Color shadowLight = Color(0x1A49505E); + + /// Default shadow color. + static const Color shadowDark = Color(0x1A49505E); } diff --git a/lib/src/theme/constants.dart b/lib/src/theme/constants.dart index 8b137891..92d3d64b 100644 --- a/lib/src/theme/constants.dart +++ b/lib/src/theme/constants.dart @@ -1 +1,21 @@ +import 'color_swatch.dart'; +/// Default font family for Zeta System +const kZetaFontFamily = 'packages/zeta_flutter/IBMPlexSans'; + +/// Primary color shade index for [ZetaColorSwatch] +const kZetaSwatchPrimaryIndex = 60; + +/// Target contrast values for different color shades of [ZetaColorSwatch] +const kZetaSwatchTargetContrasts = { + 100: 17.42, + 90: 13.99, + 80: 8.33, + 70: 6.02, + 60: 4.57, + 50: 2.66, + 40: 1.83, + 30: 1.23, + 20: 1.09, + 10: 1.02, +}; diff --git a/lib/src/theme/contrast.dart b/lib/src/theme/contrast.dart new file mode 100644 index 00000000..d406dc38 --- /dev/null +++ b/lib/src/theme/contrast.dart @@ -0,0 +1,149 @@ +/// ZetaAccessibilityStandard is an enumeration that defines the Web Content Accessibility Guidelines (WCAG) 2.1. +/// It includes two levels of conformance: AA (minimum) and AAA (enhanced). +enum ZetaContrast { + /// AA: The contrast ratio should be at least 4.57:1 + aa, + + /// AAA: The contrast ratio should be at least 8.33:1 + aaa, +} + +/// Extension on [ZetaContrast] to provide color indices +/// for certain accessibility scenarios +extension AccessibilityIndices on ZetaContrast { + /// Returns the color index value for a primary depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 60. + /// For [ZetaContrast.aaa], it returns 80. + int get primary { + switch (this) { + case ZetaContrast.aa: + return 60; + case ZetaContrast.aaa: + return 80; + } + } + + /// Returns the color index value for a surface depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 60. + /// For [ZetaContrast.aaa], it returns 80. + int get text { + switch (this) { + case ZetaContrast.aa: + return 60; + case ZetaContrast.aaa: + return 80; + } + } + + /// Returns the color index value for an icon depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 60. + /// For [ZetaContrast.aaa], it returns 80. + int get icon { + switch (this) { + case ZetaContrast.aa: + return 60; + case ZetaContrast.aaa: + return 80; + } + } + + /// Returns the color index value for a hover state depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 70. + /// For [ZetaContrast.aaa], it returns 90. + int get hover { + switch (this) { + case ZetaContrast.aa: + return 70; + case ZetaContrast.aaa: + return 90; + } + } + + /// Returns the color index value for a selected state depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 80. + /// For [ZetaContrast.aaa], it returns 100. + int get selected { + switch (this) { + case ZetaContrast.aa: + return 80; + case ZetaContrast.aaa: + return 100; + } + } + + /// Returns the color index value for a focus state depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 80. + /// For [ZetaContrast.aaa], it returns 100. + int get focus { + switch (this) { + case ZetaContrast.aa: + return 80; + case ZetaContrast.aaa: + return 100; + } + } + + /// Returns the color index value for a border depending on the ZetaContrast value. + /// + /// For [ZetaContrast.aa], it returns 60. + /// For [ZetaContrast.aaa], it returns 80. + int get border { + switch (this) { + case ZetaContrast.aa: + return 60; + case ZetaContrast.aaa: + return 80; + } + } + + /// Returns the color index value for a subtle visual element depending on the ZetaContrast value. + /// + /// For both [ZetaContrast.aa] and [ZetaContrast.aaa], it returns 40. + int get subtle { + switch (this) { + case ZetaContrast.aa: + return 40; + case ZetaContrast.aaa: + return 60; + } + } + + /// Returns the color index value for a surface depending on the ZetaContrast value. + /// + /// For both [ZetaContrast.aa] and [ZetaContrast.aaa], it returns 10. + int get surface { + switch (this) { + case ZetaContrast.aa: + return 10; + case ZetaContrast.aaa: + return 10; + } + } + + /// Returns the target contrast value. + /// + /// The getter, `targetContrast`, returns a double value that represents the + /// contrast ratio of a ZetaContrast object. The ratio can be either `4.53` or `8.33`, + /// depending on whether the contrast level of this instance is `ZetaContrast.aa` or `ZetaContrast.aaa`. + /// + /// * When the object's contrast level is `aa`, the method returns `4.53`. + /// * When the object's contrast level is `aaa`, the method returns `8.33`. + /// + /// These values serve as benchmarks for the contrast between the colours on a app's text + /// and background. Being able to measure and adjust this contrast plays a critical role in + /// improving a app's accessibility. + double get targetContrast { + switch (this) { + case ZetaContrast.aa: + return 4.53; + case ZetaContrast.aaa: + return 8.33; + } + } +} diff --git a/lib/src/theme/theme.dart b/lib/src/theme/theme.dart deleted file mode 100644 index aed90f93..00000000 --- a/lib/src/theme/theme.dart +++ /dev/null @@ -1,128 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../zeta_flutter.dart'; - -export 'breakpoints.dart'; -export 'colors.dart'; -export 'colors_base.dart'; -export 'constants.dart'; - -/// Theme for Zeta. -class ZetaTheme { - /// Default theme in light mode. - /// - /// {@template zeta-theme} - /// For apps using Zeta components to be properly themed, [Zeta] ThemeData should be placed in the widget tree using one of the following methods: - /// - /// - /// dart``` - /// MaterialApp( - /// theme: zeta, - /// ... - /// ) - /// ``` - /// - /// ``` - /// Theme( - /// data: zeta, - /// child: ... - /// ) - /// ``` - /// - /// This adds all the appropriate tokens into the app to render correctly. - /// - /// {@endtemplate} - static ThemeData zetaLight({ZetaThemeData? initialTheme}) { - return ThemeData( - colorScheme: initialTheme?.colorScheme ?? initialTheme?.zetaColors?.toColorScheme ?? ZetaColors().toColorScheme, - fontFamily: initialTheme?.fontFamily ?? 'packages/zeta_flutter/IBMPlexSans', - // TODO(tokens): reinstate tokens.Typography.fontFamily when we have a plan for tokens - textTheme: initialTheme?.textTheme ?? ZetaText.textTheme, - ); - } - - /// Default theme with dark mode. - /// - /// {@macro zeta-theme} - static ThemeData zetaDark({ZetaThemeData? initialTheme}) { - return ThemeData( - colorScheme: initialTheme?.colorScheme ?? - initialTheme?.zetaColors?.copyWith(isDarkMode: true).toColorScheme ?? - ZetaColors().toColorScheme, - fontFamily: initialTheme?.fontFamily ?? 'packages/zeta_flutter/IBMPlexSans', - textTheme: initialTheme?.textTheme ?? ZetaText.textTheme, - ); - } - - /// Builds a [ThemeData] based off of some initial data. - /// - /// If `initialTheme.zetaColors` is not defined, colors will default to light mode. - /// - /// {@macro zeta-theme} - static ThemeData builder({ZetaThemeData? initialTheme}) { - final ZetaColors colors = initialTheme?.zetaColors ?? ZetaColors(); - - return ThemeData( - colorScheme: initialTheme?.colorScheme ?? colors.toColorScheme, - fontFamily: initialTheme?.fontFamily ?? 'packages/zeta_flutter/IBMPlexSans', - textTheme: initialTheme?.textTheme ?? ZetaText.textThemeBuilder(colors), - ); - } -} - -/// Basic theme information used to create a ZetaTheme. -class ZetaThemeData { - /// Font family. - /// - /// If null, defaults to `packages/zeta_flutter/IBMPlexSans`; - final String? fontFamily; - - /// Color scheme. - /// - /// If null, defaults to `ZetaColors().toColorScheme`. - final ColorScheme? colorScheme; - - /// ZetaColors - /// - /// If null, defaults to `ZetaColors()` - which builds a light mode color palette with default Zeta Colors. - final ZetaColors? zetaColors; - - /// TextTheme. If null, defaults to [ZetaText.textTheme]. - final TextTheme? textTheme; - - /// Constructs a [ZetaThemeData]. - const ZetaThemeData({ - this.fontFamily, - this.colorScheme, - this.zetaColors, - this.textTheme, - }); - - /// Returns a new [ZetaThemeData] with fields replaced with the passed parameters. - ZetaThemeData copyWith({ - String? fontFamily, - ColorScheme? colorScheme, - ZetaColors? zetaColors, - TextTheme? textTheme, - }) { - return ZetaThemeData( - fontFamily: fontFamily ?? this.fontFamily, - colorScheme: colorScheme ?? this.colorScheme, - zetaColors: zetaColors ?? this.zetaColors, - textTheme: textTheme ?? this.textTheme, - ); - } -} - -/// Font family for whole theme. -extension FontFamily on ThemeData { - /// Default font family used by theme. - /// - /// We assume that the same font should be used for all text styles in a theme, therefore we can extract from any child theme. - String? get fontFamily => textTheme.bodyMedium?.fontFamily; - - /// Default text color used by theme. - /// - /// We assume that the same font should be used for all text styles in a theme, therefore we can extract from any child theme. - Color? get defaultColor => textTheme.bodyMedium?.color; -} diff --git a/lib/src/theme/theme_data.dart b/lib/src/theme/theme_data.dart new file mode 100644 index 00000000..9d95d801 --- /dev/null +++ b/lib/src/theme/theme_data.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; + +import 'color_extensions.dart'; +import 'colors.dart'; +import 'constants.dart'; +import 'contrast.dart'; + +export 'breakpoints.dart'; +export 'colors.dart'; +export 'colors_base.dart'; +export 'constants.dart'; + +/// A representation of the Zeta theme data. +/// +/// This class encapsulates the colors and fonts used for the Zeta theme in both light and dark modes. +@immutable +class ZetaThemeData { + /// Constructs a [ZetaThemeData]. + /// + /// If [primary] and/or [secondary] colors are provided, they will be used to create the light and dark Zeta color palettes. + ZetaThemeData({ + this.fontFamily = kZetaFontFamily, + this.identifier = 'default', + ZetaContrast contrast = ZetaContrast.aa, + ZetaColors? colorsLight, + ZetaColors? colorsDark, + Color? primary, + Color? secondary, + }) : _colorsDark = (primary != null + ? ZetaColors.dark( + contrast: contrast, + primary: primary.zetaColorSwatch, + secondary: secondary?.zetaColorSwatch, + ) + : (colorsDark ?? ZetaColors.dark())) + .apply(contrast: contrast), + _colorsLight = (primary != null + ? ZetaColors.light( + contrast: contrast, + primary: primary.zetaColorSwatch, + secondary: secondary?.zetaColorSwatch, + ) + : (colorsLight ?? ZetaColors.light())) + .apply(contrast: contrast); + + /// The font family used in the Zeta theme. + /// + /// Defaults to [kZetaFontFamily] if not provided. + final String fontFamily; + + /// An Identifier cab be assigned to identify the theme uniquely. + /// + /// It can be useful in case selected theme need to be displayed. + /// + /// Defaults to 'default'. + final String identifier; + + final ZetaColors _colorsLight; + + /// The colors used for the light mode of the Zeta theme. + /// + /// Defaults to a light mode color palette with default Zeta colors if not explicitly provided. + ZetaColors get colorsLight => _colorsLight; + + final ZetaColors _colorsDark; + + /// The colors used for the dark mode of the Zeta theme. + /// + /// Defaults to a dark mode color palette with default Zeta colors if not explicitly provided. + ZetaColors get colorsDark => _colorsDark; + + /// Applies the given [contrast] to the current [ZetaThemeData] and returns a new [ZetaThemeData] with the updated contrast. + ZetaThemeData apply({ + required ZetaContrast contrast, + }) { + return ZetaThemeData( + contrast: contrast, + identifier: identifier, + fontFamily: fontFamily, + colorsDark: colorsDark, + colorsLight: colorsLight, + ); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is ZetaThemeData && + runtimeType == other.runtimeType && + fontFamily == other.fontFamily && + identifier == other.identifier && + _colorsLight == other._colorsLight && + _colorsDark == other._colorsDark; + + @override + int get hashCode => fontFamily.hashCode ^ identifier.hashCode ^ _colorsLight.hashCode ^ _colorsDark.hashCode; +} diff --git a/lib/src/theme/theme_service.dart b/lib/src/theme/theme_service.dart new file mode 100644 index 00000000..bbc63ee5 --- /dev/null +++ b/lib/src/theme/theme_service.dart @@ -0,0 +1,25 @@ +import 'theme_data.dart'; + +/// `ZetaThemeService` is an abstract class. +/// It provides the structure for loading and saving themes in Zeta application. + +abstract class ZetaThemeService { + /// Loads the application's theme. + /// + /// `loadTheme` is a method to retrieve the current theme data. + /// + /// Returns a `Future` that completes with the `ZetaThemeData` object + /// that represents the current theme. + + Future loadTheme(); + + /// Saves the provided theme data as the application's theme. + /// + /// `saveTheme` is a method used to save the current theme data. + /// + /// Takes a `ZetaThemeData` object that represents the theme to be saved. + /// + /// Returns a `Future` that completes when the theme data has been successfully saved. + + Future saveTheme(ZetaThemeData themeData); +} diff --git a/lib/src/tokens.dart b/lib/src/tokens.dart index 00ad26c4..fdfe7837 100644 --- a/lib/src/tokens.dart +++ b/lib/src/tokens.dart @@ -99,9 +99,6 @@ class Typography { /// Zeta library contains IBM Plex Sans with latin script. /// In the case of non-latin languages, this can be overridden: /// - /// ``` theme: ZetaTheme.zeta.copyWith(fontFamily: ''),``` - // static const String fontFamily = 'packages/zeta_flutter/IBMPlexSans'; - /// Default text size. /// /// Defaults to [Dimensions.s]. diff --git a/lib/src/zeta.dart b/lib/src/zeta.dart index 085224d5..cf8a7c42 100644 --- a/lib/src/zeta.dart +++ b/lib/src/zeta.dart @@ -1,116 +1,362 @@ -import 'package:flutter/cupertino.dart'; +import 'dart:async'; + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import 'theme/contrast.dart'; +import 'theme/theme_data.dart'; +import 'theme/theme_service.dart'; -/// Wrapper widget for apps using zeta. -/// -/// Please place this widget at the top level of the application. -/// Typically this would be wrapping a [MaterialApp], [WidgetsApp] or [CupertinoApp]. +/// An [InheritedWidget] that provides access to Zeta theme settings. /// -/// Without this widget in the tree, theming and colors may not work. -class Zeta extends StatefulWidget { - /// Base theme for the app. Zeta styles will be applied on top of this. - final ZetaThemeData? theme; +/// It holds information about the current contrast, theme mode, and theme data. +/// The [colors] getter provides the correct color set based on the current theme mode. +class Zeta extends InheritedWidget { + /// Constructs a [Zeta] widget. + /// + /// The [contrast], [themeMode], [themeData], and [child] arguments are required. + const Zeta({ + super.key, + required Brightness mediaBrightness, + required this.contrast, + required this.themeMode, + required this.themeData, + required super.child, + }) : _mediaBrightness = mediaBrightness; + + /// The current contrast setting for the app, which can be one of the predefined + /// values in [ZetaContrast]. + final ZetaContrast contrast; + + /// Specifies the theme mode for the app, which determines how the UI is rendered. + /// + /// It can be one of the values: [ThemeMode.system], [ThemeMode.light], or [ThemeMode.dark]. + final ThemeMode themeMode; - /// Override for custom colors. - final ZetaColors? colors; + /// Provides the theme data for the app, which contains all the theming information. + final ZetaThemeData themeData; + + /// Internal property to get the system brightness. + /// Used to determine the theme mode when it's set to [ThemeMode.system]. + final Brightness _mediaBrightness; + + /// Provides the color set based on the current theme mode. + /// + /// It determines the appropriate color set (light or dark) based on the theme mode + /// and system brightness. + ZetaColors get colors { + if (themeMode == ThemeMode.system) { + return _mediaBrightness == Brightness.light ? themeData.colorsLight : themeData.colorsDark; + } else if (themeMode == ThemeMode.light) { + return themeData.colorsLight; + } else { + return themeData.colorsDark; + } + } - /// Builder for the app. + /// Gets the brightness setting for the current theme. /// - /// Returns theme and colors. - final Widget Function(BuildContext, ThemeData, ZetaColors) builder; + /// If the theme mode is set to 'system', it will return the brightness that ties with the device's system theme setting. + /// If the theme mode is set to 'light', it always returns `Brightness.light`. + /// If neither, it returns `Brightness.dark` by default (i.e., when the theme mode is 'dark'). + Brightness get brightness { + if (themeMode == ThemeMode.system) { + return _mediaBrightness; // Return the current system brightness setting + } else if (themeMode == ThemeMode.light) { + return Brightness.light; // Return the light mode brightness + } else { + return Brightness.dark; // Default: Return the dark mode brightness + } + } - /// Constructor for [Zeta]. - const Zeta({required this.builder, this.theme, this.colors, super.key}); @override - State createState() => ZetaState(); + bool updateShouldNotify(covariant Zeta oldWidget) { + return oldWidget.contrast != contrast || + oldWidget.themeMode != themeMode || + oldWidget.themeData != themeData || + oldWidget._mediaBrightness != _mediaBrightness; + } + + /// Fetches the [Zeta] instance from the provided [context]. + /// + /// It ensures that the context has access to the [Zeta] theming information. + /// Throws a [FlutterError] if the [Zeta] is not found in the widget tree. + static Zeta of(BuildContext context) { + final defaults = context.dependOnInheritedWidgetOfExactType(); + if (defaults != null) { + return defaults; + } else { + throw FlutterError.fromParts( + [ + ErrorDescription('Unable to find Zeta in the widget tree.'), + ErrorHint( + 'Ensure that the context passed to Zeta.of() is a descendant of a ZetaProvider widget. This usually means that ZetaProviderState should be an ancestor of the widget which uses this context.', + ), + ErrorSpacer(), + ErrorDescription('The widget for the context used was:'), + DiagnosticsProperty('widget', context.widget, showName: false), + ErrorSpacer(), + ErrorHint( + 'If you recently changed the type of that widget, or the widget tree, ensure the ZetaProvider widget is still an ancestor.', + ), + ], + ); + } + } + @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add(DiagnosticsProperty('theme', theme)); - properties.add(DiagnosticsProperty('colors', colors)); properties - .add(ObjectFlagProperty.has('builder', builder)); + ..add(EnumProperty('contrast', contrast)) + ..add(EnumProperty('themeMode', themeMode)) + ..add(DiagnosticsProperty('themeData', themeData)) + ..add(DiagnosticsProperty('colors', colors)) + ..add(EnumProperty('mediaBrightness', _mediaBrightness)) + ..add(EnumProperty('brightness', brightness)); } } -/// State for [Zeta]. -class ZetaState extends State { - ZetaColors _colors = ZetaColors(); - late ThemeData _theme; - late ZetaThemeData _zetaTheme; +/// A typedef for the ZetaAppBuilder function which takes [BuildContext], [ZetaThemeData], +/// and [ThemeMode] and returns a [Widget]. +typedef ZetaAppBuilder = Widget Function(BuildContext context, ZetaThemeData themeData, ThemeMode themeMode); - /// Theme used by zeta. - ZetaThemeData get zetaTheme => _zetaTheme; - set zetaTheme(ZetaThemeData value) { - _zetaTheme = value; - setState(() { - _theme = ZetaTheme.builder(initialTheme: zetaTheme); - }); - } +/// A widget that provides Zeta theming and contrast data down the widget tree. +class ZetaProvider extends StatefulWidget with Diagnosticable { + /// Constructs a [ZetaProvider] widget. + /// + /// The [builder] argument is required. The [initialThemeMode], [initialContrast], + /// and [initialThemeData] arguments provide initial values. + ZetaProvider({ + required this.builder, + this.initialThemeMode = ThemeMode.system, + this.initialContrast = ZetaContrast.aa, + this.themeService, + ZetaThemeData? initialThemeData, + super.key, + }) : initialThemeData = initialThemeData ?? ZetaThemeData(); - bool _ready = false; + /// Specifies the initial theme mode for the app. + /// + /// It can be one of the values: [ThemeMode.system], [ThemeMode.light], or [ThemeMode.dark]. + /// Defaults to [ThemeMode.system]. + final ThemeMode initialThemeMode; - /// Colors for app. + /// Provides the initial theme data for the app. /// - /// Access using `ZetaColors.of(context)`. - ZetaColors get colors => _colors; + /// This contains all the theming information. If not provided, + /// it defaults to a basic [ZetaThemeData] instance. + final ZetaThemeData initialThemeData; - /// Sets colors for app. + /// Specifies the initial contrast setting for the app. /// - /// Access using `ZetaColors.setColors(context, colors)`. + /// Defaults to [ZetaContrast.aa]. + final ZetaContrast initialContrast; + + /// A builder function to construct the widget tree using the provided theming information. /// - /// When called, resets top-level key to force UI rebuild of app. - set colors(ZetaColors value) { - if (_colors != value) { - setState(() { - _colors = value; - _theme = ZetaTheme.builder(initialTheme: zetaTheme.copyWith(zetaColors: value)); - }); + /// It receives the [BuildContext], [ZetaThemeData], and [ThemeMode] as arguments + /// and is expected to return a [Widget]. + final ZetaAppBuilder builder; + + /// A `ZetaThemeService` + /// + /// It provides the structure for loading and saving themes in Zeta application. + final ZetaThemeService? themeService; + + @override + State createState() => ZetaProviderState(); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('themeData', initialThemeData)) + ..add(ObjectFlagProperty.has('builder', builder)) + ..add(EnumProperty('initialThemeMode', initialThemeMode)) + ..add(EnumProperty('initialContrast', initialContrast)) + ..add(DiagnosticsProperty('themeService', themeService)); + } + + /// Retrieves the [ZetaProviderState] from the provided context. + static ZetaProviderState of(BuildContext context) { + final zetaState = context.findAncestorStateOfType(); + if (zetaState != null) { + return zetaState; + } else { + throw FlutterError.fromParts( + [ + ErrorDescription('Unable to find ZetaProviderState in the widget tree.'), + ErrorHint( + 'Ensure that the context passed to ZetaProvider.of() is a descendant of a ZetaProvider widget. This usually means that ZetaProviderState should be an ancestor of the widget which uses this context.', + ), + ErrorSpacer(), + ErrorDescription('The widget for the context used was:'), + DiagnosticsProperty('widget', context.widget, showName: false), + ErrorSpacer(), + ErrorHint( + 'If you recently changed the type of that widget, or the widget tree, ensure the ZetaProvider widget is still an ancestor.', + ), + ], + ); } } +} + +/// The state associated with [ZetaProvider]. +class ZetaProviderState extends State with Diagnosticable, WidgetsBindingObserver { + // Fields for ZetaThemeManager. + + /// Represents the late initialization of the ZetaContrast value. + late ZetaContrast _contrast; + /// Represents the late initialization of the ThemeMode value. + late ThemeMode _themeMode; + + /// Represents the late initialization of the ZetaThemeData object. + late ZetaThemeData _themeData; + + /// Represents the late initialization of the system's current brightness (dark or light mode). + late Brightness _platformBrightness; + + /// Represents a nullable brightness value to be used for brightness change debouncing. + Brightness? _debounceBrightness; + + /// Timer used for debouncing brightness changes. + Timer? _debounceTimer; + + /// Represents the duration for the debounce timer. + static const _debounceDuration = Duration(milliseconds: 500); + + /// This method is called when this object is inserted into the tree. + /// + /// Here, it also adds this object as an observer in [WidgetsBinding] instance + /// and initializes various fields related to the theme, contrast, and brightness of the app. @override void initState() { super.initState(); + WidgetsBinding.instance.addObserver(this); + + // Set the initial brightness with the system's current brightness from the first view of the platform dispatcher. + _platformBrightness = MediaQueryData.fromView(PlatformDispatcher.instance.views.first).platformBrightness; + + // Set the initial theme mode. + _themeMode = widget.initialThemeMode; + + // Set the initial contrast. + _contrast = widget.initialContrast; + + // Apply the initial contrast to the theme data. + _themeData = widget.initialThemeData.apply(contrast: _contrast); - zetaTheme = (widget.theme ?? const ZetaThemeData()).copyWith(zetaColors: colors); - colors = widget.colors ?? ZetaColors(); - _ready = true; + // Load theme data from themeService if available. + unawaited( + widget.themeService?.loadTheme().then((value) { + if (value != null) { + setState(() { + _themeData = value; + }); + } + }), + ); } + /// Clean up function to be called when this object is removed from the tree. + /// + /// This also removes this object as an observer from the [WidgetsBinding] instance. @override - void didUpdateWidget(Zeta oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.colors != widget.colors) { - colors = widget.colors ?? ZetaColors(); - zetaTheme = (widget.theme ?? const ZetaThemeData()).copyWith(zetaColors: colors); - } - if (oldWidget.theme != widget.theme) { - zetaTheme = (widget.theme ?? const ZetaThemeData()).copyWith(zetaColors: colors); + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + /// Overrides the [didChangePlatformBrightness] method from the parent class. + /// + /// This method gets information about the platform's brightness and updates the app if it ever changes. + /// The changes are debounced with a timer to avoid them being too frequent. + @override + void didChangePlatformBrightness() { + super.didChangePlatformBrightness(); + + // Get the platform brightness from the first view of the platform dispatcher + // `_debounceBrightness` will then hold the new brightness + _debounceBrightness = MediaQueryData.fromView(PlatformDispatcher.instance.views.first).platformBrightness; + + // If the current stored brightness value is different from the newly fetched value + if (_platformBrightness != _debounceBrightness) { + // If brightness has changed, cancel the existing timer and start a new one + + // Cancel existing timer if any + _debounceTimer?.cancel(); + + // Start a new timer with `_debounceDuration` delay + _debounceTimer = Timer(_debounceDuration, () { + // Once timer fires, check if brightness is still different and not null + if (_debounceBrightness != null && _platformBrightness != _debounceBrightness) { + // If brightness value has indeed changed, update the state + setState(() { + // Set the new brightness value + _platformBrightness = _debounceBrightness!; + }); + } + }); } } @override Widget build(BuildContext context) { - if (_ready) { - return Theme( - data: _theme, - child: Builder( - builder: (context) => widget.builder(context, _theme, colors), - ), - ); + return Zeta( + themeMode: _themeMode, + themeData: _themeData, + contrast: _contrast, + mediaBrightness: _platformBrightness, + child: widget.builder(context, _themeData, _themeMode), + ); + } + + @override + void didUpdateWidget(ZetaProvider oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.initialContrast != widget.initialContrast || + oldWidget.initialThemeMode != widget.initialThemeMode || + oldWidget.initialThemeData != widget.initialThemeData) { + setState(() { + _themeMode = widget.initialThemeMode; + _contrast = widget.initialContrast; + _themeData = widget.initialThemeData.apply(contrast: _contrast); + }); } + } - return const SizedBox(); + /// Updates the current theme mode. + void updateThemeMode(ThemeMode themeMode) { + setState(() { + _themeMode = themeMode; + }); + } + + /// Updates the current theme data. + void updateThemeData(ZetaThemeData data) { + setState(() { + _themeData = data.apply(contrast: _contrast); + unawaited(widget.themeService?.saveTheme(data)); + }); + } + + /// Updates the current contrast. + void updateContrast(ZetaContrast contrast) { + setState(() { + _contrast = contrast; + _themeData = _themeData.apply(contrast: contrast); + }); } @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add(DiagnosticsProperty('colors', colors)); - properties.add(DiagnosticsProperty('zetaTheme', zetaTheme)); + properties + ..add(DiagnosticsProperty('themeData', _themeData)) + ..add(EnumProperty('contrast', _contrast)) + ..add(EnumProperty('themeMode', _themeMode)); } } diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index b657f5bc..eecb1b7a 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -4,8 +4,12 @@ library zeta_flutter; export 'src/components/grid.dart'; export 'src/components/spacing.dart'; export 'src/components/text.dart'; +export 'src/theme/color_extensions.dart'; +export 'src/theme/color_scheme.dart'; +export 'src/theme/color_swatch.dart'; export 'src/theme/constants.dart'; -export 'src/theme/theme.dart'; +export 'src/theme/contrast.dart'; +export 'src/theme/theme_data.dart'; export 'src/tokens.dart'; export 'src/utils/extensions.dart'; export 'src/zeta.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 3cc6946f..564d0e43 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,9 +1,9 @@ name: zeta_flutter -version: 0.0.1+12 -description: Zebra Design System (Zeta) - Flutter Component Library -homepage: https://github.com/zebradevs/zeta-flutter -repository: https://github.com/zebradevs/zeta-flutter -issue_tracker: https://github.com/zebradevs/zeta-flutter/issues +version: 0.1.0+1 +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 +issue_tracker: https://github.com/zebradevs/zeta_flutter/issues documentation: https://zeta-ds.web.app/flutter/dartdoc/index.html platforms: @@ -14,7 +14,6 @@ platforms: windows: linux: - environment: sdk: ">=3.0.1 <4.0.0" flutter: ">=3.7.0" @@ -26,6 +25,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + zds_analysis: ^1.0.0 flutter: fonts: From f333429083f0cf790627211788e69285bcff3a37 Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Fri, 1 Dec 2023 11:57:57 +0200 Subject: [PATCH 03/41] Cleanup dart warnings; fix text scale (#23) * fix endtemplate in comments; upgrade flutter packages * remove unnecessary text scaling * [automated commit] lint format and import sort --------- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions --- CHANGELOG.md | 22 ++++++++++++++++++++++ lib/src/components/text.dart | 3 +-- lib/src/theme/color_swatch.dart | 1 + lib/src/theme/colors.dart | 4 ++-- pubspec.yaml | 7 +++++-- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d554425..fb9ed5ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +## [0.1.0+2] - 2023-12-01 +### :wrench: Chores +- [`d22dd29`](https://github.com/zebratechnologies/zeta-flutter/commit/d22dd29b506affccc8cdc7ecfb15a57fcf330646) - Tidy, reorganise and prepare repo *(commit by [@thelukewalton](https://github.com/thelukewalton))* + +### :flying_saucer: Other Changes +- [`199328c`](https://github.com/zebratechnologies/zeta-flutter/commit/199328c28ccfa8a05a1494c08ad93aaf13dd3b28) - Update to mirror 0.1.0+1 from ZebraDevs *(commit by [@thelukewalton](https://github.com/thelukewalton))* +- [`0ee6171`](https://github.com/zebratechnologies/zeta-flutter/commit/0ee6171e779c6db9995308aa35f2f598b9db372c) - Cleanup dart warnings; fix text scale ([#23](https://github.com/zebratechnologies/zeta-flutter/pull/23)) + +* fix endtemplate in comments; upgrade flutter packages + +* remove unnecessary text scaling + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + ## [0.1.0+1] - 2023-11-28 - chore: Tidy, reorganise and prepare repo @@ -177,3 +197,5 @@ Introduced license details for third-party libraries used in the project. MIT li - Initial setup [0.0.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+11...0.0.1+12 + +[0.1.0+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+12...0.1.0+2 \ No newline at end of file diff --git a/lib/src/components/text.dart b/lib/src/components/text.dart index 4132446e..172488ef 100644 --- a/lib/src/components/text.dart +++ b/lib/src/components/text.dart @@ -717,8 +717,7 @@ class ZetaText extends StatelessWidget { final Color color = textColor ?? Zeta.of(context).colors.textDefault; thisStyle = thisStyle.copyWith( - fontSize: (fontSize ?? thisStyle.fontSize ?? tokens.Typography.defaultTextSize) * - MediaQuery.of(context).textScaleFactor, + fontSize: fontSize ?? thisStyle.fontSize ?? tokens.Typography.defaultTextSize, height: _fontSize, fontWeight: fontWeight, decoration: decoration ?? TextDecoration.none, diff --git a/lib/src/theme/color_swatch.dart b/lib/src/theme/color_swatch.dart index 5b8f8acd..405a0440 100644 --- a/lib/src/theme/color_swatch.dart +++ b/lib/src/theme/color_swatch.dart @@ -27,6 +27,7 @@ class ZetaColorSwatch extends ColorSwatch { /// /// It ensures that the 60th and 80th shades from swatch are abide by the AA and AAA accessibility standards on [background], respectively. /// [background] color defaults to [ZetaColorBase.greyWarm] shade10. + /// {@endtemplate} factory ZetaColorSwatch.fromColor( Color primary, { Brightness brightness = Brightness.light, diff --git a/lib/src/theme/colors.dart b/lib/src/theme/colors.dart index c54f270f..955df4d7 100644 --- a/lib/src/theme/colors.dart +++ b/lib/src/theme/colors.dart @@ -224,7 +224,7 @@ class ZetaColors { /// /// {@template zeta-color-dark} /// Color swatches are inverted if [ZetaColors.brightness] is Dark. - /// {@endTemplate} + /// {@endtemplate} Color get textDefault => cool.shade90; /// Subtle text /icon color. @@ -258,7 +258,7 @@ class ZetaColors { /// /// {@template zeta-color-dark} /// Color swatches are inverted if [ZetaColors.brightness] is Dark. - /// {@endTemplate} + /// {@endtemplate} Color get iconDefault => textDefault; /// Subtle icon color. diff --git a/pubspec.yaml b/pubspec.yaml index 564d0e43..5ab7cfc1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,8 @@ name: zeta_flutter -version: 0.1.0+1 -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. +version: 0.1.0+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 issue_tracker: https://github.com/zebradevs/zeta_flutter/issues @@ -14,6 +16,7 @@ platforms: windows: linux: + environment: sdk: ">=3.0.1 <4.0.0" flutter: ">=3.7.0" From 0794b08d029e9954457dbfac56bd576aaf8f0e82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 10:41:12 +0000 Subject: [PATCH 04/41] chore(deps): bump tj-actions/branch-names in /.github/workflows (#26) Bumps [tj-actions/branch-names](https://github.com/tj-actions/branch-names) from 5.1 to 7.0.7. - [Release notes](https://github.com/tj-actions/branch-names/releases) - [Changelog](https://github.com/tj-actions/branch-names/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/branch-names/compare/v5.1...v7.0.7) --- updated-dependencies: - dependency-name: tj-actions/branch-names dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/pr.yml | 2 +- CHANGELOG.md | 40 ++++++++++++++++++++++++++++++---------- pubspec.yaml | 2 +- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 6b5bcf3a..ad790cbb 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -46,7 +46,7 @@ jobs: fi - name: Get branch name id: branch-name - uses: tj-actions/branch-names@v5.1 + uses: tj-actions/branch-names@v7.0.7 - uses: subosito/flutter-action@v2 with: flutter-version: "3.13.x" diff --git a/CHANGELOG.md b/CHANGELOG.md index fb9ed5ae..d18f5f34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## [0.1.0+3] - 2023-12-06 +### :wrench: Chores +- [`63b94a6`](https://github.com/zebratechnologies/zeta-flutter/commit/63b94a60da570ce3848aa9c1af7a129a2c952399) - **deps**: bump tj-actions/branch-names in /.github/workflows *(PR [#26](https://github.com/zebratechnologies/zeta-flutter/pull/26) by [@dependabot[bot]](https://github.com/apps/dependabot))* + +### :flying_saucer: Other Changes +- [`f333429`](https://github.com/zebratechnologies/zeta-flutter/commit/f333429083f0cf790627211788e69285bcff3a37) - Cleanup dart warnings; fix text scale ([#23](https://github.com/zebratechnologies/zeta-flutter/pull/23)) + +* fix endtemplate in comments; upgrade flutter packages + +* remove unnecessary text scaling + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + ## [0.1.0+2] - 2023-12-01 ### :wrench: Chores - [`d22dd29`](https://github.com/zebratechnologies/zeta-flutter/commit/d22dd29b506affccc8cdc7ecfb15a57fcf330646) - Tidy, reorganise and prepare repo *(commit by [@thelukewalton](https://github.com/thelukewalton))* @@ -6,15 +25,15 @@ - [`199328c`](https://github.com/zebratechnologies/zeta-flutter/commit/199328c28ccfa8a05a1494c08ad93aaf13dd3b28) - Update to mirror 0.1.0+1 from ZebraDevs *(commit by [@thelukewalton](https://github.com/thelukewalton))* - [`0ee6171`](https://github.com/zebratechnologies/zeta-flutter/commit/0ee6171e779c6db9995308aa35f2f598b9db372c) - Cleanup dart warnings; fix text scale ([#23](https://github.com/zebratechnologies/zeta-flutter/pull/23)) -* fix endtemplate in comments; upgrade flutter packages - -* remove unnecessary text scaling - -* [automated commit] lint format and import sort - ---------- - -Co-authored-by: Atanas Yordanov +* fix endtemplate in comments; upgrade flutter packages + +* remove unnecessary text scaling + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -198,4 +217,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.0.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+11...0.0.1+12 -[0.1.0+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+12...0.1.0+2 \ No newline at end of file +[0.1.0+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+12...0.1.0+2 +[0.1.0+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+2...0.1.0+3 \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 5ab7cfc1..acd2641b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.0+2 +version: 0.1.0+3 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. From ef44d244589a7cc652a934f25a5122bbd1657c05 Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Wed, 6 Dec 2023 15:04:51 +0200 Subject: [PATCH 05/41] status_label (#25) * status_label * [automated commit] lint format and import sort * spacing changes * extract BorderType in utils * chore(deps): bump tj-actions/branch-names in /.github/workflows (#26) Bumps [tj-actions/branch-names](https://github.com/tj-actions/branch-names) from 5.1 to 7.0.7. - [Release notes](https://github.com/tj-actions/branch-names/releases) - [Changelog](https://github.com/tj-actions/branch-names/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/branch-names/compare/v5.1...v7.0.7) --- updated-dependencies: - dependency-name: tj-actions/branch-names dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [automated commit] lint format and import sort --------- Signed-off-by: dependabot[bot] Co-authored-by: github-actions Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- CHANGELOG.md | 43 +++- example/lib/home.dart | 2 + example/lib/pages/status_label_example.dart | 55 +++++ example/pubspec.lock | 10 +- example/test/status_label_test.dart | 55 +++++ .../components/status_label_widgetbook.dart | 30 +++ example/widgetbook/widgetbook.dart | 2 + lib/src/components/status_label.dart | 196 ++++++++++++++++++ lib/src/utils/enums.dart | 8 + lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 11 files changed, 397 insertions(+), 7 deletions(-) create mode 100644 example/lib/pages/status_label_example.dart create mode 100644 example/test/status_label_test.dart create mode 100644 example/widgetbook/components/status_label_widgetbook.dart create mode 100644 lib/src/components/status_label.dart create mode 100644 lib/src/utils/enums.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index d18f5f34..40b072f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,43 @@ +## [0.1.0+4] - 2023-12-06 +### :wrench: Chores +- [`0794b08`](https://github.com/zebratechnologies/zeta-flutter/commit/0794b08d029e9954457dbfac56bd576aaf8f0e82) - **deps**: bump tj-actions/branch-names in /.github/workflows *(PR [#26](https://github.com/zebratechnologies/zeta-flutter/pull/26) by [@dependabot[bot]](https://github.com/apps/dependabot))* + +### :flying_saucer: Other Changes +- [`65bf57f`](https://github.com/zebratechnologies/zeta-flutter/commit/65bf57fc1d7f13d4017b0e21f5f52d62552b502c) - status_label ([#25](https://github.com/zebratechnologies/zeta-flutter/pull/25)) + +* status_label + +* [automated commit] lint format and import sort + +* spacing changes + +* extract BorderType in utils + +* chore(deps): bump tj-actions/branch-names in /.github/workflows ([#26](https://github.com/zebratechnologies/zeta-flutter/pull/26)) + +Bumps [tj-actions/branch-names](https://github.com/tj-actions/branch-names) from 5.1 to 7.0.7. +- [Release notes](https://github.com/tj-actions/branch-names/releases) +- [Changelog](https://github.com/tj-actions/branch-names/blob/main/HISTORY.md) +- [Commits](https://github.com/tj-actions/branch-names/compare/v5.1...v7.0.7) + +--- +updated-dependencies: +- dependency-name: tj-actions/branch-names + dependency-type: direct:production +... + +Signed-off-by: dependabot[bot] +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> + +* [automated commit] lint format and import sort + +--------- + +Signed-off-by: dependabot[bot] +Co-authored-by: github-actions +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + ## [0.1.0+3] - 2023-12-06 ### :wrench: Chores - [`63b94a6`](https://github.com/zebratechnologies/zeta-flutter/commit/63b94a60da570ce3848aa9c1af7a129a2c952399) - **deps**: bump tj-actions/branch-names in /.github/workflows *(PR [#26](https://github.com/zebratechnologies/zeta-flutter/pull/26) by [@dependabot[bot]](https://github.com/apps/dependabot))* @@ -218,4 +258,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.0.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+11...0.0.1+12 [0.1.0+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+12...0.1.0+2 -[0.1.0+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+2...0.1.0+3 \ No newline at end of file +[0.1.0+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+2...0.1.0+3 +[0.1.0+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+3...0.1.0+4 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index ad1381d3..43e1c117 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -3,6 +3,7 @@ import 'package:go_router/go_router.dart'; import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/grid_example.dart'; import 'package:zeta_example/pages/spacing_example.dart'; +import 'package:zeta_example/pages/status_label_example.dart'; import 'package:zeta_example/pages/typography_example.dart'; import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; @@ -19,6 +20,7 @@ final List components = [ Component(SpacingExample.name, (context) => const SpacingExample()), Component(TypographyExample.name, (context) => const TypographyExample()), Component(ColorExample.name, (context) => const ColorExample()), + Component(LabelExample.name, (context) => const LabelExample()), ]; class Home extends StatefulWidget { diff --git a/example/lib/pages/status_label_example.dart b/example/lib/pages/status_label_example.dart new file mode 100644 index 00000000..e0d1bef4 --- /dev/null +++ b/example/lib/pages/status_label_example.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:zeta_flutter/src/utils/enums.dart'; + +import '../widgets.dart'; + +class LabelExample extends StatelessWidget { + static const String name = 'StatusLabel'; + + const LabelExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: LabelExample.name, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + statusLabelExampleRow(ZetaStatusLabelType.neutral), + statusLabelExampleRow(ZetaStatusLabelType.info), + statusLabelExampleRow(ZetaStatusLabelType.positive), + statusLabelExampleRow(ZetaStatusLabelType.warning), + statusLabelExampleRow(ZetaStatusLabelType.negative), + statusLabelExampleRow( + ZetaStatusLabelType.custom, + colors: ZetaStatusLabelColors(accentColor: Colors.blue, backgroundColor: Colors.blue.shade50), + ), + ], + ), + ), + ); + } +} + +Widget statusLabelExampleRow(ZetaStatusLabelType type, {ZetaStatusLabelColors? colors}) { + return Padding( + padding: EdgeInsets.all(10), + child: + Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ + ZetaStatusLabel( + label: 'Label', + labelType: type, + isDefaultIcon: false, + customColors: colors, + ), + ZetaStatusLabel( + label: 'Label', + labelType: type, + borderType: BorderType.rounded, + customColors: colors, + ), + ]), + ); +} diff --git a/example/pubspec.lock b/example/pubspec.lock index f4af5a61..a7342d64 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -353,18 +353,18 @@ packages: dependency: "direct dev" description: name: widgetbook - sha256: e3e4d710f0348da28209b8ec35617b0a425542a3c61889199dddf2b531b159bb + sha256: "37bb71322ed2b024b4b321f9ac0791f6b4510a9abcd42a108c11bec97ac4688a" url: "https://pub.dev" source: hosted - version: "3.4.1" + version: "3.5.0" win32: dependency: transitive description: name: win32 - sha256: "7c99c0e1e2fa190b48d25c81ca5e42036d5cac81430ef249027d97b0935c553f" + sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.1.1" xdg_directories: dependency: transitive description: @@ -379,7 +379,7 @@ packages: path: ".." relative: true source: path - version: "0.1.0+1" + version: "0.1.0+3" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/status_label_test.dart b/example/test/status_label_test.dart new file mode 100644 index 00000000..9eeaca88 --- /dev/null +++ b/example/test/status_label_test.dart @@ -0,0 +1,55 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:flutter/material.dart'; + +void main() { + group('ZetaStatusLabel Tests', () { + testWidgets('Initializes with correct properties', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidgetStatusLabel( + widget: ZetaStatusLabel(label: 'Test Label'), + ), + ); + expect(find.text('Test Label'), findsOneWidget); + }); + }); + + testWidgets('Initializes with correct label and custom icon', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidgetStatusLabel( + widget: ZetaStatusLabel( + label: 'Custom Icon', + isDefaultIcon: false, + customIcon: Icons.person, + ), + ), + ); + expect(find.text('Custom Icon'), findsOneWidget); + expect(find.byIcon(Icons.person), findsOneWidget); + }); +} + +class TestWidgetStatusLabel extends StatelessWidget { + final Widget widget; + + const TestWidgetStatusLabel({Key? key, required this.widget}); + + @override + Widget build(BuildContext context) { + return ZetaProvider( + builder: (context, theme, __) { + return Builder(builder: (context) { + return MaterialApp( + theme: ThemeData( + fontFamily: theme.fontFamily, + textTheme: ZetaText.textTheme, + ), + home: Scaffold( + body: widget, + ), + ); + }); + }, + ); + } +} diff --git a/example/widgetbook/components/status_label_widgetbook.dart b/example/widgetbook/components/status_label_widgetbook.dart new file mode 100644 index 00000000..43b61601 --- /dev/null +++ b/example/widgetbook/components/status_label_widgetbook.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/status_label_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent statusLabelWidgetBook() { + return WidgetbookComponent( + name: 'StatusLabel', + useCases: [ + WidgetbookUseCase( + name: 'Status Label', + builder: (context) => SingleChildScrollView( + child: Column( + children: [ + statusLabelExampleRow(ZetaStatusLabelType.neutral), + statusLabelExampleRow(ZetaStatusLabelType.info), + statusLabelExampleRow(ZetaStatusLabelType.positive), + statusLabelExampleRow(ZetaStatusLabelType.warning), + statusLabelExampleRow(ZetaStatusLabelType.negative), + statusLabelExampleRow( + ZetaStatusLabelType.custom, + colors: ZetaStatusLabelColors(accentColor: Colors.blue, backgroundColor: Colors.blue.shade50), + ), + ], + ), + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index e1c128e3..c9283044 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -5,6 +5,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; import 'components/color_widgetbook.dart'; import 'components/grid_widgetbook.dart'; import 'components/spacing_widgetbook.dart'; +import 'components/status_label_widgetbook.dart'; import 'components/typography_widgetbook.dart'; import 'utils/zebra.dart'; @@ -24,6 +25,7 @@ class HotReload extends StatelessWidget { spacingWidgetbook(), textWidgetBook(), colorWidgetBook(), + statusLabelWidgetBook(), ], ), ], diff --git a/lib/src/components/status_label.dart b/lib/src/components/status_label.dart new file mode 100644 index 00000000..303c7c9c --- /dev/null +++ b/lib/src/components/status_label.dart @@ -0,0 +1,196 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '../../zeta_flutter.dart'; +import '../utils/enums.dart'; + +///Zeta Status Label Colors +class ZetaStatusLabelColors { + ///Constructs [ZetaStatusLabelColors]. + const ZetaStatusLabelColors({ + required this.backgroundColor, + required this.accentColor, + }); + + ///Background Color + final Color backgroundColor; + + ///Border and Icon Color + final Color accentColor; +} + +/// Status Label Type +enum ZetaStatusLabelType { + ///Grey Label + neutral, + + ///Purple Label + info, + + ///Green Label + positive, + + ///Yellow Label + warning, + + ///Red Label + negative, + + ///Custom Label + custom +} + +///Zeta Status Label +class ZetaStatusLabel extends StatelessWidget { + ///Constructs [ZetaStatusLabel]. + const ZetaStatusLabel({ + required this.label, + this.labelType = ZetaStatusLabelType.neutral, + this.isDefaultIcon = true, + this.customIcon, + this.borderType = BorderType.sharp, + this.labelSize = const Size(80, 25), + this.borderWidth = 1, + this.customColors, + this.customIconSize = 20.0, + super.key, + }); + + ///The type of border to display + /// + /// Defaults to sharp + final BorderType borderType; + + ///Width of the label border + /// + /// Defaults to 1 + final double borderWidth; + + ///Size of the label + final Size labelSize; + + ///The type of the label + /// + /// Defaults to "neutral" + final ZetaStatusLabelType labelType; + + ///Label + final String label; + + ///Colors for the label + final ZetaStatusLabelColors? customColors; + + ///Whether the icon is the default icon + /// + ///Defaults to true + final bool isDefaultIcon; + + ///Custom icon + final IconData? customIcon; + + ///The size of the custom icon + /// + ///Defaults to 20 + final double customIconSize; + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + final colors = _getColors(theme); + return Container( + height: labelSize.height, + decoration: _buildDecoration(colors), + constraints: BoxConstraints(minWidth: labelSize.width), + child: _buildContent(colors, theme), + ); + } + + BoxDecoration _buildDecoration(ZetaStatusLabelColors colors) { + return BoxDecoration( + color: colors.backgroundColor, + border: Border.all(color: colors.accentColor, width: borderWidth), + borderRadius: BorderRadius.circular(borderType == BorderType.rounded ? 15.0 : 0.0), + ); + } + + Widget _buildContent(ZetaStatusLabelColors colors, Zeta theme) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: Dimensions.xxs), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + _buildIcon(colors), + const SizedBox(width: Dimensions.xs), + Flexible( + child: Text( + label, + style: ZetaText.zetaTitleMedium, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ); + } + + Icon _buildIcon(ZetaStatusLabelColors colors) { + final size = isDefaultIcon ? 12.0 : customIconSize; + return Icon( + size: size, + isDefaultIcon ? Icons.circle : (customIcon ?? Icons.star), + color: colors.accentColor, + ); + } + + ZetaStatusLabelColors _getColors(Zeta theme) { + final defaultColorScheme = ZetaStatusLabelColors( + backgroundColor: theme.colors.surfaceDisabled, + accentColor: theme.colors.borderDefault, + ); + switch (labelType) { + case ZetaStatusLabelType.neutral: + return defaultColorScheme; + case ZetaStatusLabelType.info: + return ZetaStatusLabelColors( + backgroundColor: theme.colors.purple.shade10, + accentColor: theme.colors.purple.shade50, + ); + case ZetaStatusLabelType.positive: + return ZetaStatusLabelColors( + backgroundColor: theme.colors.green.shade10, + accentColor: theme.colors.green.shade50, + ); + case ZetaStatusLabelType.warning: + return ZetaStatusLabelColors( + backgroundColor: theme.colors.orange.shade10, + accentColor: theme.colors.orange.shade50, + ); + case ZetaStatusLabelType.negative: + return ZetaStatusLabelColors( + backgroundColor: theme.colors.red.shade10, + accentColor: theme.colors.red.shade50, + ); + case ZetaStatusLabelType.custom: + return customColors ?? defaultColorScheme; + } + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('borderType', borderType)) + ..add(DoubleProperty('borderWidth', borderWidth)) + ..add(DiagnosticsProperty('labelSize', labelSize)) + ..add(EnumProperty('labelType', labelType)) + ..add(StringProperty('label', label)) + ..add( + DiagnosticsProperty( + 'customColors', + customColors, + ), + ) + ..add(DiagnosticsProperty('isDefaultIcon', isDefaultIcon)) + ..add(DiagnosticsProperty('customIcon', customIcon)) + ..add(DoubleProperty('customIconSize', customIconSize)); + } +} diff --git a/lib/src/utils/enums.dart b/lib/src/utils/enums.dart new file mode 100644 index 00000000..5a98cae7 --- /dev/null +++ b/lib/src/utils/enums.dart @@ -0,0 +1,8 @@ +///Border Types +enum BorderType { + ///sharp border + sharp, + + ///rounded border + rounded, +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index eecb1b7a..17e99869 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -3,6 +3,7 @@ library zeta_flutter; export 'src/components/grid.dart'; export 'src/components/spacing.dart'; +export 'src/components/status_label.dart'; export 'src/components/text.dart'; export 'src/theme/color_extensions.dart'; export 'src/theme/color_scheme.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index acd2641b..0b2b2478 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.0+3 +version: 0.1.0+4 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. From 2f21a18e30425fe91fe7bb0ee3c4df7ab8baca35 Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Fri, 8 Dec 2023 12:21:25 +0200 Subject: [PATCH 06/41] add icons (#24) * add icons * [automated commit] lint format and import sort * [automated commit] lint format and import sort --------- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions --- CHANGELOG.md | 108 ++- example/lib/home.dart | 2 + example/lib/pages/icons_example.dart | 1019 +++++++++++++++++++++ example/pubspec.lock | 2 +- lib/src/assets/fonts/zeta-icons-round.ttf | Bin 0 -> 145320 bytes lib/src/assets/fonts/zeta-icons-sharp.ttf | Bin 0 -> 116564 bytes lib/src/icons.dart | 1008 ++++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 8 +- 9 files changed, 2117 insertions(+), 31 deletions(-) create mode 100644 example/lib/pages/icons_example.dart create mode 100644 lib/src/assets/fonts/zeta-icons-round.ttf create mode 100644 lib/src/assets/fonts/zeta-icons-sharp.ttf create mode 100644 lib/src/icons.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 40b072f7..fd695cd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,40 +1,89 @@ -## [0.1.0+4] - 2023-12-06 -### :wrench: Chores -- [`0794b08`](https://github.com/zebratechnologies/zeta-flutter/commit/0794b08d029e9954457dbfac56bd576aaf8f0e82) - **deps**: bump tj-actions/branch-names in /.github/workflows *(PR [#26](https://github.com/zebratechnologies/zeta-flutter/pull/26) by [@dependabot[bot]](https://github.com/apps/dependabot))* - +## [0.1.0+5] - 2023-12-08 ### :flying_saucer: Other Changes -- [`65bf57f`](https://github.com/zebratechnologies/zeta-flutter/commit/65bf57fc1d7f13d4017b0e21f5f52d62552b502c) - status_label ([#25](https://github.com/zebratechnologies/zeta-flutter/pull/25)) +- [`ef44d24`](https://github.com/zebratechnologies/zeta-flutter/commit/ef44d244589a7cc652a934f25a5122bbd1657c05) - status_label ([#25](https://github.com/zebratechnologies/zeta-flutter/pull/25)) + +* status_label + +* [automated commit] lint format and import sort + +* spacing changes + +* extract BorderType in utils + +* chore(deps): bump tj-actions/branch-names in /.github/workflows ([#26](https://github.com/zebratechnologies/zeta-flutter/pull/26)) + +Bumps [tj-actions/branch-names](https://github.com/tj-actions/branch-names) from 5.1 to 7.0.7. +- [Release notes](https://github.com/tj-actions/branch-names/releases) +- [Changelog](https://github.com/tj-actions/branch-names/blob/main/HISTORY.md) +- [Commits](https://github.com/tj-actions/branch-names/compare/v5.1...v7.0.7) + +--- +updated-dependencies: +- dependency-name: tj-actions/branch-names + dependency-type: direct:production +... -* status_label +Signed-off-by: dependabot[bot] +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> + +* [automated commit] lint format and import sort + +--------- + +Signed-off-by: dependabot[bot] +Co-authored-by: github-actions +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`c90349b`](https://github.com/zebratechnologies/zeta-flutter/commit/c90349b104f3000956f821934b01dfd74f37a5e2) - add icons ([#24](https://github.com/zebratechnologies/zeta-flutter/pull/24)) + +* add icons * [automated commit] lint format and import sort -* spacing changes - -* extract BorderType in utils - -* chore(deps): bump tj-actions/branch-names in /.github/workflows ([#26](https://github.com/zebratechnologies/zeta-flutter/pull/26)) - -Bumps [tj-actions/branch-names](https://github.com/tj-actions/branch-names) from 5.1 to 7.0.7. -- [Release notes](https://github.com/tj-actions/branch-names/releases) -- [Changelog](https://github.com/tj-actions/branch-names/blob/main/HISTORY.md) -- [Commits](https://github.com/tj-actions/branch-names/compare/v5.1...v7.0.7) - ---- -updated-dependencies: -- dependency-name: tj-actions/branch-names - dependency-type: direct:production -... - -Signed-off-by: dependabot[bot] -Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - * [automated commit] lint format and import sort --------- -Signed-off-by: dependabot[bot] -Co-authored-by: github-actions +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + +## [0.1.0+4] - 2023-12-06 +### :wrench: Chores +- [`0794b08`](https://github.com/zebratechnologies/zeta-flutter/commit/0794b08d029e9954457dbfac56bd576aaf8f0e82) - **deps**: bump tj-actions/branch-names in /.github/workflows *(PR [#26](https://github.com/zebratechnologies/zeta-flutter/pull/26) by [@dependabot[bot]](https://github.com/apps/dependabot))* + +### :flying_saucer: Other Changes +- [`65bf57f`](https://github.com/zebratechnologies/zeta-flutter/commit/65bf57fc1d7f13d4017b0e21f5f52d62552b502c) - status_label ([#25](https://github.com/zebratechnologies/zeta-flutter/pull/25)) + +* status_label + +* [automated commit] lint format and import sort + +* spacing changes + +* extract BorderType in utils + +* chore(deps): bump tj-actions/branch-names in /.github/workflows ([#26](https://github.com/zebratechnologies/zeta-flutter/pull/26)) + +Bumps [tj-actions/branch-names](https://github.com/tj-actions/branch-names) from 5.1 to 7.0.7. +- [Release notes](https://github.com/tj-actions/branch-names/releases) +- [Changelog](https://github.com/tj-actions/branch-names/blob/main/HISTORY.md) +- [Commits](https://github.com/tj-actions/branch-names/compare/v5.1...v7.0.7) + +--- +updated-dependencies: +- dependency-name: tj-actions/branch-names + dependency-type: direct:production +... + +Signed-off-by: dependabot[bot] +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> + +* [automated commit] lint format and import sort + +--------- + +Signed-off-by: dependabot[bot] +Co-authored-by: github-actions Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* @@ -259,4 +308,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.0+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+12...0.1.0+2 [0.1.0+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+2...0.1.0+3 -[0.1.0+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+3...0.1.0+4 \ No newline at end of file +[0.1.0+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+3...0.1.0+4 +[0.1.0+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+4...0.1.0+5 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 43e1c117..2b7ca782 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/grid_example.dart'; +import 'package:zeta_example/pages/icons_example.dart'; import 'package:zeta_example/pages/spacing_example.dart'; import 'package:zeta_example/pages/status_label_example.dart'; import 'package:zeta_example/pages/typography_example.dart'; @@ -20,6 +21,7 @@ final List components = [ Component(SpacingExample.name, (context) => const SpacingExample()), Component(TypographyExample.name, (context) => const TypographyExample()), Component(ColorExample.name, (context) => const ColorExample()), + Component(IconsExample.name, (context) => const IconsExample()), Component(LabelExample.name, (context) => const LabelExample()), ]; diff --git a/example/lib/pages/icons_example.dart b/example/lib/pages/icons_example.dart new file mode 100644 index 00000000..756bdd1d --- /dev/null +++ b/example/lib/pages/icons_example.dart @@ -0,0 +1,1019 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class IconsExample extends StatefulWidget { + static const String name = 'Icons'; + + const IconsExample({super.key}); + + @override + State createState() => _IconsExampleState(); +} + +class _IconsExampleState extends State { + bool showGeneratedColors = false; + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: IconsExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + ZetaText.bodyLarge('Round'), + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + // round + Icon(ZetaIcons.alarm_round), + Icon(ZetaIcons.ar_round), + Icon(ZetaIcons.bookmark_outline_round), + Icon(ZetaIcons.bookmark_round), + Icon(ZetaIcons.build_round), + Icon(ZetaIcons.cached_round), + Icon(ZetaIcons.calendar_3_day_round), + Icon(ZetaIcons.calendar_alt_1_round), + Icon(ZetaIcons.calendar_alt_2_round), + Icon(ZetaIcons.calendar_available_round), + Icon(ZetaIcons.calendar_cancel_round), + Icon(ZetaIcons.calendar_day_round), + Icon(ZetaIcons.calendar_edit_round), + Icon(ZetaIcons.calendar_monthly_alt_round), + Icon(ZetaIcons.calendar_monthly_round), + Icon(ZetaIcons.calendar_range_round), + Icon(ZetaIcons.calendar_round), + Icon(ZetaIcons.calendar_weekly_alt_round), + Icon(ZetaIcons.calendar_weekly_round), + Icon(ZetaIcons.calendar_yearly_round), + Icon(ZetaIcons.check_circle_outline_alt_round), + Icon(ZetaIcons.check_circle_outline_round), + Icon(ZetaIcons.check_circle_round), + Icon(ZetaIcons.check_mark_round), + Icon(ZetaIcons.clipboard_round), + Icon(ZetaIcons.clock_outline_round), + Icon(ZetaIcons.clock_round), + Icon(ZetaIcons.credit_card_round), + Icon(ZetaIcons.delete_forever_round), + Icon(ZetaIcons.delete_outline_round), + Icon(ZetaIcons.delete_round), + Icon(ZetaIcons.dislike_action_round), + Icon(ZetaIcons.document_round), + Icon(ZetaIcons.download_round), + Icon(ZetaIcons.filter_alt_round), + Icon(ZetaIcons.filter_round), + Icon(ZetaIcons.hand_round), + Icon(ZetaIcons.history_round), + Icon(ZetaIcons.home_round), + Icon(ZetaIcons.info_round), + Icon(ZetaIcons.label_round), + Icon(ZetaIcons.like_action_round), + Icon(ZetaIcons.lock_alt_round), + Icon(ZetaIcons.lock_round), + Icon(ZetaIcons.log_in_round), + Icon(ZetaIcons.log_out_round), + Icon(ZetaIcons.love_outline_round), + Icon(ZetaIcons.love_round), + Icon(ZetaIcons.open_in_full_round), + Icon(ZetaIcons.open_in_new_window_round), + Icon(ZetaIcons.pending_round), + Icon(ZetaIcons.pin_round), + Icon(ZetaIcons.price_round), + Icon(ZetaIcons.renew_round), + Icon(ZetaIcons.search_round), + Icon(ZetaIcons.security_check_round), + Icon(ZetaIcons.settings_round), + Icon(ZetaIcons.sync_action_round), + Icon(ZetaIcons.touch_round), + Icon(ZetaIcons.trending_down_round), + Icon(ZetaIcons.trending_up_round), + Icon(ZetaIcons.unlock_alt_round), + Icon(ZetaIcons.unlock_round), + Icon(ZetaIcons.update_round), + Icon(ZetaIcons.upload_round), + Icon(ZetaIcons.user_circle_round), + Icon(ZetaIcons.user_round), + Icon(ZetaIcons.user_settings_round), + Icon(ZetaIcons.verified_round), + Icon(ZetaIcons.visibility_off_round), + Icon(ZetaIcons.visibility_round), + Icon(ZetaIcons.world_action_round), + Icon(ZetaIcons.zoom_in_round), + Icon(ZetaIcons.zoom_out_round), + Icon(ZetaIcons.add_alert_round), + Icon(ZetaIcons.alert_round), + Icon(ZetaIcons.auto_delete_round), + Icon(ZetaIcons.error_outline_round), + Icon(ZetaIcons.error_round), + Icon(ZetaIcons.important_notification_round), + Icon(ZetaIcons.warning_outline_round), + Icon(ZetaIcons.warning_round), + Icon(ZetaIcons.block_round), + Icon(ZetaIcons.closed_caption_round), + Icon(ZetaIcons.fast_forward_round), + Icon(ZetaIcons.fast_rewind_round), + Icon(ZetaIcons.loop_round), + Icon(ZetaIcons.microphone_off_round), + Icon(ZetaIcons.microphone_outline_round), + Icon(ZetaIcons.microphone_round), + Icon(ZetaIcons.pause_circle_round), + Icon(ZetaIcons.pause_round), + Icon(ZetaIcons.play_circle_round), + Icon(ZetaIcons.play_outline_round), + Icon(ZetaIcons.play_round), + Icon(ZetaIcons.replay_round), + Icon(ZetaIcons.skip_next_round), + Icon(ZetaIcons.skip_previous_round), + Icon(ZetaIcons.stop_circle_round), + Icon(ZetaIcons.stop_round), + Icon(ZetaIcons.video_camera_round), + Icon(ZetaIcons.volume_down_round), + Icon(ZetaIcons.volume_mute_round), + Icon(ZetaIcons.volume_off_round), + Icon(ZetaIcons.volume_up_round), + Icon(ZetaIcons.add_call_round), + Icon(ZetaIcons.chat_bubble_outline_round), + Icon(ZetaIcons.chat_bubble_round), + Icon(ZetaIcons.conversation_round), + Icon(ZetaIcons.dialpad_round), + Icon(ZetaIcons.do_not_disturb_round), + Icon(ZetaIcons.dollar_round), + Icon(ZetaIcons.email_alt_round), + Icon(ZetaIcons.email_outline_round), + Icon(ZetaIcons.email_round), + Icon(ZetaIcons.end_call_round), + Icon(ZetaIcons.message_round), + Icon(ZetaIcons.person_search_round), + Icon(ZetaIcons.phone_bluetooth_speaker_round), + Icon(ZetaIcons.phone_in_talk_round), + Icon(ZetaIcons.phone_round), + Icon(ZetaIcons.priority_round), + Icon(ZetaIcons.qr_code_round), + Icon(ZetaIcons.qr_code_scan_round), + Icon(ZetaIcons.rss_feed_round), + Icon(ZetaIcons.sd_card_round), + Icon(ZetaIcons.sim_card_round), + Icon(ZetaIcons.sms_round), + Icon(ZetaIcons.sync_disabled_round), + Icon(ZetaIcons.sync_round), + Icon(ZetaIcons.add_box_round), + Icon(ZetaIcons.add_circle_outline_round), + Icon(ZetaIcons.add_circle_round), + Icon(ZetaIcons.add_round), + Icon(ZetaIcons.analysis_round), + Icon(ZetaIcons.android_round), + Icon(ZetaIcons.backspace_round), + Icon(ZetaIcons.block_content_round), + Icon(ZetaIcons.clear_round), + Icon(ZetaIcons.content_round), + Icon(ZetaIcons.copy_file_round), + Icon(ZetaIcons.create_round), + Icon(ZetaIcons.filter_list_round), + Icon(ZetaIcons.flag_round), + Icon(ZetaIcons.link_content_round), + Icon(ZetaIcons.mail_round), + Icon(ZetaIcons.push_pin_round), + Icon(ZetaIcons.redo_round), + Icon(ZetaIcons.remove_box_round), + Icon(ZetaIcons.remove_circle_outline_round), + Icon(ZetaIcons.remove_circle_round), + Icon(ZetaIcons.remove_round), + Icon(ZetaIcons.reply_round), + Icon(ZetaIcons.save_alt_round), + Icon(ZetaIcons.save_round), + Icon(ZetaIcons.send_round), + Icon(ZetaIcons.sort_round), + Icon(ZetaIcons.undo_round), + Icon(ZetaIcons.antenna_round), + Icon(ZetaIcons.battery_alert_round), + Icon(ZetaIcons.battery_charging_round), + Icon(ZetaIcons.battery_round), + Icon(ZetaIcons.bluetooth_disabled_round), + Icon(ZetaIcons.bluetooth_round), + Icon(ZetaIcons.bluetooth_searching_round), + Icon(ZetaIcons.brightness_round), + Icon(ZetaIcons.cellular_signal_round), + Icon(ZetaIcons.chain_round), + Icon(ZetaIcons.contrast_round), + Icon(ZetaIcons.dark_mode_round), + Icon(ZetaIcons.devices_round), + Icon(ZetaIcons.ethernet_round), + Icon(ZetaIcons.flight_mode_round), + Icon(ZetaIcons.hdmi_round), + Icon(ZetaIcons.light_mode_round), + Icon(ZetaIcons.location_point_round), + Icon(ZetaIcons.location_round), + Icon(ZetaIcons.mobile_friendly_round), + Icon(ZetaIcons.network_signal_round), + Icon(ZetaIcons.nfc_round), + Icon(ZetaIcons.night_round), + Icon(ZetaIcons.restart_alt_round), + Icon(ZetaIcons.screen_rotation_round), + Icon(ZetaIcons.uhf_rfid_round), + Icon(ZetaIcons.usb_alt_device_round), + Icon(ZetaIcons.usb_alt_round), + Icon(ZetaIcons.usb_round), + Icon(ZetaIcons.volte_round), + Icon(ZetaIcons.appgallery_round), + Icon(ZetaIcons.application_analytics_round), + Icon(ZetaIcons.asset_tracker_lite_round), + Icon(ZetaIcons.blood_bag_plus_round), + Icon(ZetaIcons.bluetooth_management_round), + Icon(ZetaIcons.browser_print_round), + Icon(ZetaIcons.cloud_connect_round), + Icon(ZetaIcons.data_wedge_round), + Icon(ZetaIcons.design_tools_round), + Icon(ZetaIcons.device_tracker_round), + Icon(ZetaIcons.direct_connect_round), + Icon(ZetaIcons.emdk_round), + Icon(ZetaIcons.enterprise_browser_round), + Icon(ZetaIcons.enterprise_connectors_round), + Icon(ZetaIcons.enterprise_keyboard_round), + Icon(ZetaIcons.gms_restricted_mode_round), + Icon(ZetaIcons.intelligent_document_capture_round), + Icon(ZetaIcons.label_plus_round), + Icon(ZetaIcons.life_guard_round), + Icon(ZetaIcons.link_os_round), + Icon(ZetaIcons.mdm_connectors_round), + Icon(ZetaIcons.mdm_toolkit_round), + Icon(ZetaIcons.mobility_dna_round), + Icon(ZetaIcons.mobility_security_round), + Icon(ZetaIcons.multi_code_data_formatting_round), + Icon(ZetaIcons.mx_round), + Icon(ZetaIcons.ocr_round), + Icon(ZetaIcons.oem_config_round), + Icon(ZetaIcons.pairing_solutions_round), + Icon(ZetaIcons.pdf_direct_round), + Icon(ZetaIcons.power_precision_round), + Icon(ZetaIcons.preferred_symbol_round), + Icon(ZetaIcons.print_secure_round), + Icon(ZetaIcons.print_station_round), + Icon(ZetaIcons.printer_profile_manager_round), + Icon(ZetaIcons.przm_round), + Icon(ZetaIcons.remote_control_round), + Icon(ZetaIcons.remote_diagnostics_round), + Icon(ZetaIcons.remote_management_round), + Icon(ZetaIcons.rx_round), + Icon(ZetaIcons.scan_and_pair_round), + Icon(ZetaIcons.scan_speed_analytics_round), + Icon(ZetaIcons.scan_to_connect_round), + Icon(ZetaIcons.scanner_control_application_round), + Icon(ZetaIcons.setting_tool_round), + Icon(ZetaIcons.simulscan_round), + Icon(ZetaIcons.smart_te_lite_round), + Icon(ZetaIcons.smart_te_round), + Icon(ZetaIcons.smart_tek_round), + Icon(ZetaIcons.smartdex_round), + Icon(ZetaIcons.stagenow_round), + Icon(ZetaIcons.swipe_assist_round), + Icon(ZetaIcons.tekspeech_pro_round), + Icon(ZetaIcons.virtual_devices_round), + Icon(ZetaIcons.virtual_tether_round), + Icon(ZetaIcons.visibility_services_round), + Icon(ZetaIcons.voice_wedge_round), + Icon(ZetaIcons.workforce_connect_round), + Icon(ZetaIcons.workstation_connect_round), + Icon(ZetaIcons.zebra_designer_round), + Icon(ZetaIcons.zebra_onecare_round), + Icon(ZetaIcons.zebra_setup_utility_round), + Icon(ZetaIcons.zero_touch_round), + Icon(ZetaIcons.align_center_round), + Icon(ZetaIcons.align_horizontal_center_round), + Icon(ZetaIcons.align_horizontal_left_round), + Icon(ZetaIcons.align_horizontal_right_round), + Icon(ZetaIcons.align_left_round), + Icon(ZetaIcons.align_right_round), + Icon(ZetaIcons.align_vertical_bottom_round), + Icon(ZetaIcons.align_vertical_center_round), + Icon(ZetaIcons.align_vertical_top_round), + Icon(ZetaIcons.attach_round), + Icon(ZetaIcons.bold_round), + Icon(ZetaIcons.bullet_list_round), + Icon(ZetaIcons.checklist_round), + Icon(ZetaIcons.color_fill_round), + Icon(ZetaIcons.distribute_horizontal_round), + Icon(ZetaIcons.distribute_vertical_round), + Icon(ZetaIcons.edit_border_round), + Icon(ZetaIcons.edit_round), + Icon(ZetaIcons.font_size_decrease_round), + Icon(ZetaIcons.font_size_increase_round), + Icon(ZetaIcons.format_shapes_round), + Icon(ZetaIcons.indent_decrease_round), + Icon(ZetaIcons.indent_increase_round), + Icon(ZetaIcons.italic_round), + Icon(ZetaIcons.justify_round), + Icon(ZetaIcons.line_spacing_round), + Icon(ZetaIcons.link_round), + Icon(ZetaIcons.no_color_round), + Icon(ZetaIcons.numbered_list_round), + Icon(ZetaIcons.strikethrough_round), + Icon(ZetaIcons.text_color_round), + Icon(ZetaIcons.type_round), + Icon(ZetaIcons.underline_round), + Icon(ZetaIcons.barcode_bluetooth_round), + Icon(ZetaIcons.barcode_done_round), + Icon(ZetaIcons.barcode_image_scan_round), + Icon(ZetaIcons.barcode_qr_code_round), + Icon(ZetaIcons.barcode_round), + Icon(ZetaIcons.barcode_scanner_down_round), + Icon(ZetaIcons.barcode_settings_round), + Icon(ZetaIcons.calculator_round), + Icon(ZetaIcons.card_orientation_round), + Icon(ZetaIcons.card_with_chip_round), + Icon(ZetaIcons.certificate_round), + Icon(ZetaIcons.choices_round), + Icon(ZetaIcons.contactless_pay_round), + Icon(ZetaIcons.credit_card_swipe_round), + Icon(ZetaIcons.eas_round), + Icon(ZetaIcons.enterprise_diagnostics_round), + Icon(ZetaIcons.environmental_round), + Icon(ZetaIcons.factory_round), + Icon(ZetaIcons.freezer_round), + Icon(ZetaIcons.issue_audit_round), + Icon(ZetaIcons.performance_round), + Icon(ZetaIcons.planogram_round), + Icon(ZetaIcons.productivity_apps_round), + Icon(ZetaIcons.receipt_round), + Icon(ZetaIcons.retail_round), + Icon(ZetaIcons.road_map_round), + Icon(ZetaIcons.rules_round), + Icon(ZetaIcons.scan_rate_round), + Icon(ZetaIcons.shape_recognition_round), + Icon(ZetaIcons.solutions_round), + Icon(ZetaIcons.steps_round), + Icon(ZetaIcons.strategy_round), + Icon(ZetaIcons.tap_to_pay_round), + Icon(ZetaIcons.zero_scale_round), + Icon(ZetaIcons.attachment_round), + Icon(ZetaIcons.cloud_done_round), + Icon(ZetaIcons.cloud_download_round), + Icon(ZetaIcons.cloud_off_round), + Icon(ZetaIcons.cloud_outline_round), + Icon(ZetaIcons.cloud_round), + Icon(ZetaIcons.cloud_upload_round), + Icon(ZetaIcons.create_new_folder_round), + Icon(ZetaIcons.doc_attach_round), + Icon(ZetaIcons.downloading_round), + Icon(ZetaIcons.file_download_round), + Icon(ZetaIcons.file_upload_round), + Icon(ZetaIcons.finished_download_round), + Icon(ZetaIcons.folder_outline_round), + Icon(ZetaIcons.folder_round), + Icon(ZetaIcons.grid_view_round), + Icon(ZetaIcons.jpg_attach_round), + Icon(ZetaIcons.pdf_attach_round), + Icon(ZetaIcons.png_attach_round), + Icon(ZetaIcons.ppt_attach_round), + Icon(ZetaIcons.shared_folder_round), + Icon(ZetaIcons.upload_file_round), + Icon(ZetaIcons.cast_connected_round), + Icon(ZetaIcons.cast_round), + Icon(ZetaIcons.desktop_round), + Icon(ZetaIcons.device_settings_round), + Icon(ZetaIcons.devices_ecosystem_round), + Icon(ZetaIcons.headphones_round), + Icon(ZetaIcons.keyboard_round), + Icon(ZetaIcons.laptop_round), + Icon(ZetaIcons.memory_round), + Icon(ZetaIcons.monitor_round), + Icon(ZetaIcons.phone_android_round), + Icon(ZetaIcons.phone_iphone_round), + Icon(ZetaIcons.phonelink_round), + Icon(ZetaIcons.printer_round), + Icon(ZetaIcons.scanner_round), + Icon(ZetaIcons.security_round), + Icon(ZetaIcons.smart_phone_round), + Icon(ZetaIcons.speaker_round), + Icon(ZetaIcons.tablet_mac_round), + Icon(ZetaIcons.tablet_round), + Icon(ZetaIcons.tv_round), + Icon(ZetaIcons.video_play_round), + Icon(ZetaIcons.watch_round), + Icon(ZetaIcons.adjustments_round), + Icon(ZetaIcons.auto_round), + Icon(ZetaIcons.awb_round), + Icon(ZetaIcons.camera_round), + Icon(ZetaIcons.camera_shutter_round), + Icon(ZetaIcons.contrast_image_round), + Icon(ZetaIcons.crop_round), + Icon(ZetaIcons.eye_dropper_round), + Icon(ZetaIcons.flip_camera_round), + Icon(ZetaIcons.grid_off_round), + Icon(ZetaIcons.grid_on_round), + Icon(ZetaIcons.hdr_round), + Icon(ZetaIcons.image_library_round), + Icon(ZetaIcons.image_round), + Icon(ZetaIcons.iso_round), + Icon(ZetaIcons.portrait_round), + Icon(ZetaIcons.pro_round), + Icon(ZetaIcons.rotate_left_round), + Icon(ZetaIcons.rotate_right_round), + Icon(ZetaIcons.slide_show_round), + Icon(ZetaIcons.straighten_round), + Icon(ZetaIcons.timer_round), + Icon(ZetaIcons.visibility_image_round), + Icon(ZetaIcons.visibility_off_image_round), + Icon(ZetaIcons.wb_image_round), + Icon(ZetaIcons.wb_round), + Icon(ZetaIcons.bus_round), + Icon(ZetaIcons.cafe_round), + Icon(ZetaIcons.car_round), + Icon(ZetaIcons.flight_round), + Icon(ZetaIcons.layers_round), + Icon(ZetaIcons.light_rail_train_round), + Icon(ZetaIcons.local_shipping_round), + Icon(ZetaIcons.map_round), + Icon(ZetaIcons.my_location_round), + Icon(ZetaIcons.navigation_round), + Icon(ZetaIcons.near_me_round), + Icon(ZetaIcons.offer_round), + Icon(ZetaIcons.place_round), + Icon(ZetaIcons.ship_round), + Icon(ZetaIcons.taxi_round), + Icon(ZetaIcons.train_round), + Icon(ZetaIcons.world_round), + Icon(ZetaIcons.zoom_in_map_round), + Icon(ZetaIcons.zoom_out_map_round), + Icon(ZetaIcons.apps_round), + Icon(ZetaIcons.arrow_back_round), + Icon(ZetaIcons.arrow_down_round), + Icon(ZetaIcons.arrow_forward_round), + Icon(ZetaIcons.arrow_up_round), + Icon(ZetaIcons.cancel_outline_round), + Icon(ZetaIcons.cancel_round), + Icon(ZetaIcons.caret_down_round), + Icon(ZetaIcons.caret_left_round), + Icon(ZetaIcons.caret_right_round), + Icon(ZetaIcons.caret_sort_round), + Icon(ZetaIcons.caret_up_round), + Icon(ZetaIcons.check_round), + Icon(ZetaIcons.chevron_left_round), + Icon(ZetaIcons.chevron_right_round), + Icon(ZetaIcons.close_round), + Icon(ZetaIcons.columns_round), + Icon(ZetaIcons.dashboard_round), + Icon(ZetaIcons.drop_down_circle_round), + Icon(ZetaIcons.expand_less_round), + Icon(ZetaIcons.expand_more_round), + Icon(ZetaIcons.first_page_round), + Icon(ZetaIcons.full_screen_exit_round), + Icon(ZetaIcons.full_screen_round), + Icon(ZetaIcons.hamburger_menu_navigation_rail_round), + Icon(ZetaIcons.hamburger_menu_round), + Icon(ZetaIcons.hamburger_menu_thick_round), + Icon(ZetaIcons.help_outline_round), + Icon(ZetaIcons.help_round), + Icon(ZetaIcons.last_page_round), + Icon(ZetaIcons.list_alt_round), + Icon(ZetaIcons.list_round), + Icon(ZetaIcons.more_horizontal_round), + Icon(ZetaIcons.more_vertical_round), + Icon(ZetaIcons.refresh_round), + Icon(ZetaIcons.unfold_less_round), + Icon(ZetaIcons.unfold_more_round), + Icon(ZetaIcons.add_group_round), + Icon(ZetaIcons.add_person_round), + Icon(ZetaIcons.bad_mood_round), + Icon(ZetaIcons.blog_round), + Icon(ZetaIcons.dislike_round), + Icon(ZetaIcons.facebook_round), + Icon(ZetaIcons.group_round), + Icon(ZetaIcons.groups_round), + Icon(ZetaIcons.happy_round), + Icon(ZetaIcons.instagram_round), + Icon(ZetaIcons.ios_share_round), + Icon(ZetaIcons.like_round), + Icon(ZetaIcons.linkedin_round), + Icon(ZetaIcons.medium_round), + Icon(ZetaIcons.notifications_active_round), + Icon(ZetaIcons.notifications_outline_round), + Icon(ZetaIcons.notifications_round), + Icon(ZetaIcons.person_outline_round), + Icon(ZetaIcons.person_round), + Icon(ZetaIcons.remove_group_round), + Icon(ZetaIcons.remove_person_round), + Icon(ZetaIcons.sad_round), + Icon(ZetaIcons.satisfied_round), + Icon(ZetaIcons.share_round), + Icon(ZetaIcons.switch_user_round), + Icon(ZetaIcons.twitter_round), + Icon(ZetaIcons.very_satisfied_round), + Icon(ZetaIcons.world_map_round), + Icon(ZetaIcons.youtube_round), + Icon(ZetaIcons.check_box_empty_round), + Icon(ZetaIcons.check_box_round), + Icon(ZetaIcons.indeterminate_check_box_round), + Icon(ZetaIcons.radio_button_checked_round), + Icon(ZetaIcons.radio_button_unchecked_round), + Icon(ZetaIcons.star_half_round), + Icon(ZetaIcons.star_outline_round), + Icon(ZetaIcons.star_round), + Icon(ZetaIcons.toggle_off_round), + Icon(ZetaIcons.toggle_on_round), + ], + ), + const SizedBox(height: 20), + ZetaText.bodyLarge('Sharp'), + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + Icon(ZetaIcons.alarm_sharp), + Icon(ZetaIcons.ar_sharp), + Icon(ZetaIcons.bookmark_outline_sharp), + Icon(ZetaIcons.bookmark_sharp), + Icon(ZetaIcons.build_sharp), + Icon(ZetaIcons.cached_sharp), + Icon(ZetaIcons.calendar_3_day_sharp), + Icon(ZetaIcons.calendar_alt_1_sharp), + Icon(ZetaIcons.calendar_alt_2_sharp), + Icon(ZetaIcons.calendar_available_sharp), + Icon(ZetaIcons.calendar_cancel_sharp), + Icon(ZetaIcons.calendar_day_sharp), + Icon(ZetaIcons.calendar_edit_sharp), + Icon(ZetaIcons.calendar_monthly_alt_sharp), + Icon(ZetaIcons.calendar_monthly_sharp), + Icon(ZetaIcons.calendar_range_sharp), + Icon(ZetaIcons.calendar_sharp), + Icon(ZetaIcons.calendar_weekly_alt_sharp), + Icon(ZetaIcons.calendar_weekly_sharp), + Icon(ZetaIcons.calendar_yearly_sharp), + Icon(ZetaIcons.check_circle_outline_alt_sharp), + Icon(ZetaIcons.check_circle_outline_sharp), + Icon(ZetaIcons.check_circle_sharp), + Icon(ZetaIcons.check_mark_sharp), + Icon(ZetaIcons.clipboard_sharp), + Icon(ZetaIcons.clock_outline_sharp), + Icon(ZetaIcons.clock_sharp), + Icon(ZetaIcons.credit_card_sharp), + Icon(ZetaIcons.delete_forever_sharp), + Icon(ZetaIcons.delete_outline_sharp), + Icon(ZetaIcons.delete_sharp), + Icon(ZetaIcons.dislike_action_sharp), + Icon(ZetaIcons.document_sharp), + Icon(ZetaIcons.download_sharp), + Icon(ZetaIcons.filter_alt_sharp), + Icon(ZetaIcons.filter_sharp), + Icon(ZetaIcons.hand_sharp), + Icon(ZetaIcons.history_sharp), + Icon(ZetaIcons.home_sharp), + Icon(ZetaIcons.info_sharp), + Icon(ZetaIcons.label_sharp), + Icon(ZetaIcons.like_action_sharp), + Icon(ZetaIcons.lock_alt_sharp), + Icon(ZetaIcons.lock_sharp), + Icon(ZetaIcons.log_in_sharp), + Icon(ZetaIcons.log_out_sharp), + Icon(ZetaIcons.love_outline_sharp), + Icon(ZetaIcons.love_sharp), + Icon(ZetaIcons.open_in_full_sharp), + Icon(ZetaIcons.open_in_new_window_sharp), + Icon(ZetaIcons.pending_sharp), + Icon(ZetaIcons.pin_sharp), + Icon(ZetaIcons.price_sharp), + Icon(ZetaIcons.renew_sharp), + Icon(ZetaIcons.search_sharp), + Icon(ZetaIcons.security_check_sharp), + Icon(ZetaIcons.settings_sharp), + Icon(ZetaIcons.sync_action_sharp), + Icon(ZetaIcons.touch_sharp), + Icon(ZetaIcons.trending_down_sharp), + Icon(ZetaIcons.trending_up_sharp), + Icon(ZetaIcons.unlock_alt_sharp), + Icon(ZetaIcons.unlock_sharp), + Icon(ZetaIcons.update_sharp), + Icon(ZetaIcons.upload_sharp), + Icon(ZetaIcons.user_circle_sharp), + Icon(ZetaIcons.user_sharp), + Icon(ZetaIcons.user_settings_sharp), + Icon(ZetaIcons.verified_sharp), + Icon(ZetaIcons.visibility_off_sharp), + Icon(ZetaIcons.visibility_sharp), + Icon(ZetaIcons.world_action_sharp), + Icon(ZetaIcons.zoom_in_sharp), + Icon(ZetaIcons.zoom_out_sharp), + Icon(ZetaIcons.add_alert_sharp), + Icon(ZetaIcons.alert_sharp), + Icon(ZetaIcons.auto_delete_sharp), + Icon(ZetaIcons.error_outline_sharp), + Icon(ZetaIcons.error_sharp), + Icon(ZetaIcons.important_notification_sharp), + Icon(ZetaIcons.warning_outline_sharp), + Icon(ZetaIcons.warning_sharp), + Icon(ZetaIcons.block_sharp), + Icon(ZetaIcons.closed_caption_sharp), + Icon(ZetaIcons.fast_forward_sharp), + Icon(ZetaIcons.fast_rewind_sharp), + Icon(ZetaIcons.loop_sharp), + Icon(ZetaIcons.microphone_off_sharp), + Icon(ZetaIcons.microphone_outline_sharp), + Icon(ZetaIcons.microphone_sharp), + Icon(ZetaIcons.pause_circle_sharp), + Icon(ZetaIcons.pause_sharp), + Icon(ZetaIcons.play_circle_sharp), + Icon(ZetaIcons.play_outline_sharp), + Icon(ZetaIcons.play_sharp), + Icon(ZetaIcons.replay_sharp), + Icon(ZetaIcons.skip_next_sharp), + Icon(ZetaIcons.skip_previous_sharp), + Icon(ZetaIcons.stop_circle_sharp), + Icon(ZetaIcons.stop_sharp), + Icon(ZetaIcons.video_camera_sharp), + Icon(ZetaIcons.volume_down_sharp), + Icon(ZetaIcons.volume_mute_sharp), + Icon(ZetaIcons.volume_off_sharp), + Icon(ZetaIcons.volume_up_sharp), + Icon(ZetaIcons.add_call_sharp), + Icon(ZetaIcons.chat_bubble_outline_sharp), + Icon(ZetaIcons.chat_bubble_sharp), + Icon(ZetaIcons.conversation_sharp), + Icon(ZetaIcons.dialpad_sharp), + Icon(ZetaIcons.do_not_disturb_sharp), + Icon(ZetaIcons.dollar_sharp), + Icon(ZetaIcons.email_alt_sharp), + Icon(ZetaIcons.email_outline_sharp), + Icon(ZetaIcons.email_sharp), + Icon(ZetaIcons.end_call_sharp), + Icon(ZetaIcons.message_sharp), + Icon(ZetaIcons.person_search_sharp), + Icon(ZetaIcons.phone_bluetooth_speaker_sharp), + Icon(ZetaIcons.phone_in_talk_sharp), + Icon(ZetaIcons.phone_sharp), + Icon(ZetaIcons.priority_sharp), + Icon(ZetaIcons.qr_code_sharp), + Icon(ZetaIcons.qr_code_scan_sharp), + Icon(ZetaIcons.rss_feed_sharp), + Icon(ZetaIcons.sd_card_sharp), + Icon(ZetaIcons.sim_card_sharp), + Icon(ZetaIcons.sms_sharp), + Icon(ZetaIcons.sync_disabled_sharp), + Icon(ZetaIcons.sync_sharp), + Icon(ZetaIcons.add_box_sharp), + Icon(ZetaIcons.add_circle_outline_sharp), + Icon(ZetaIcons.add_circle_sharp), + Icon(ZetaIcons.add_sharp), + Icon(ZetaIcons.analysis_sharp), + Icon(ZetaIcons.android_sharp), + Icon(ZetaIcons.backspace_sharp), + Icon(ZetaIcons.block_content_sharp), + Icon(ZetaIcons.clear_sharp), + Icon(ZetaIcons.content_sharp), + Icon(ZetaIcons.copy_file_sharp), + Icon(ZetaIcons.create_sharp), + Icon(ZetaIcons.filter_list_sharp), + Icon(ZetaIcons.flag_sharp), + Icon(ZetaIcons.link_content_sharp), + Icon(ZetaIcons.mail_sharp), + Icon(ZetaIcons.push_pin_sharp), + Icon(ZetaIcons.redo_sharp), + Icon(ZetaIcons.remove_box_sharp), + Icon(ZetaIcons.remove_circle_outline_sharp), + Icon(ZetaIcons.remove_circle_sharp), + Icon(ZetaIcons.remove_sharp), + Icon(ZetaIcons.reply_sharp), + Icon(ZetaIcons.save_alt_sharp), + Icon(ZetaIcons.save_sharp), + Icon(ZetaIcons.send_sharp), + Icon(ZetaIcons.sort_sharp), + Icon(ZetaIcons.undo_sharp), + Icon(ZetaIcons.antenna_sharp), + Icon(ZetaIcons.battery_alert_sharp), + Icon(ZetaIcons.battery_charging_sharp), + Icon(ZetaIcons.battery_sharp), + Icon(ZetaIcons.bluetooth_disabled_sharp), + Icon(ZetaIcons.bluetooth_sharp), + Icon(ZetaIcons.bluetooth_searching_sharp), + Icon(ZetaIcons.brightness_sharp), + Icon(ZetaIcons.cellular_signal_sharp), + Icon(ZetaIcons.chain_sharp), + Icon(ZetaIcons.contrast_sharp), + Icon(ZetaIcons.dark_mode_sharp), + Icon(ZetaIcons.devices_sharp), + Icon(ZetaIcons.ethernet_sharp), + Icon(ZetaIcons.flight_mode_sharp), + Icon(ZetaIcons.hdmi_sharp), + Icon(ZetaIcons.light_mode_sharp), + Icon(ZetaIcons.location_point_sharp), + Icon(ZetaIcons.location_sharp), + Icon(ZetaIcons.mobile_friendly_sharp), + Icon(ZetaIcons.network_signal_sharp), + Icon(ZetaIcons.nfc_sharp), + Icon(ZetaIcons.night_sharp), + Icon(ZetaIcons.restart_alt_sharp), + Icon(ZetaIcons.screen_rotation_sharp), + Icon(ZetaIcons.uhf_rfid_sharp), + Icon(ZetaIcons.usb_alt_device_sharp), + Icon(ZetaIcons.usb_alt_sharp), + Icon(ZetaIcons.usb_sharp), + Icon(ZetaIcons.volte_sharp), + Icon(ZetaIcons.appgallery_sharp), + Icon(ZetaIcons.application_analytics_sharp), + Icon(ZetaIcons.asset_tracker_lite_sharp), + Icon(ZetaIcons.blood_bag_plus_sharp), + Icon(ZetaIcons.bluetooth_management_sharp), + Icon(ZetaIcons.browser_print_sharp), + Icon(ZetaIcons.cloud_connect_sharp), + Icon(ZetaIcons.data_wedge_sharp), + Icon(ZetaIcons.design_tools_sharp), + Icon(ZetaIcons.device_tracker_sharp), + Icon(ZetaIcons.direct_connect_sharp), + Icon(ZetaIcons.emdk_sharp), + Icon(ZetaIcons.enterprise_browser_sharp), + Icon(ZetaIcons.enterprise_connectors_sharp), + Icon(ZetaIcons.enterprise_keyboard_sharp), + Icon(ZetaIcons.gms_restricted_mode_sharp), + Icon(ZetaIcons.intelligent_document_capture_sharp), + Icon(ZetaIcons.label_plus_sharp), + Icon(ZetaIcons.life_guard_sharp), + Icon(ZetaIcons.link_os_sharp), + Icon(ZetaIcons.mdm_connectors_sharp), + Icon(ZetaIcons.mdm_toolkit_sharp), + Icon(ZetaIcons.mobility_dna_sharp), + Icon(ZetaIcons.mobility_security_sharp), + Icon(ZetaIcons.multi_code_data_formatting_sharp), + Icon(ZetaIcons.mx_sharp), + Icon(ZetaIcons.ocr_sharp), + Icon(ZetaIcons.oem_config_sharp), + Icon(ZetaIcons.pairing_solutions_sharp), + Icon(ZetaIcons.pdf_direct_sharp), + Icon(ZetaIcons.power_precision_sharp), + Icon(ZetaIcons.preferred_symbol_sharp), + Icon(ZetaIcons.print_secure_sharp), + Icon(ZetaIcons.print_station_sharp), + Icon(ZetaIcons.printer_profile_manager_sharp), + Icon(ZetaIcons.przm_sharp), + Icon(ZetaIcons.remote_control_sharp), + Icon(ZetaIcons.remote_diagnostics_sharp), + Icon(ZetaIcons.remote_management_sharp), + Icon(ZetaIcons.rx_sharp), + Icon(ZetaIcons.scan_and_pair_sharp), + Icon(ZetaIcons.scan_speed_analytics_sharp), + Icon(ZetaIcons.scan_to_connect_sharp), + Icon(ZetaIcons.scanner_control_application_sharp), + Icon(ZetaIcons.setting_tool_sharp), + Icon(ZetaIcons.simulscan_sharp), + Icon(ZetaIcons.smart_te_lite_sharp), + Icon(ZetaIcons.smart_te_sharp), + Icon(ZetaIcons.smart_tek_sharp), + Icon(ZetaIcons.smartdex_sharp), + Icon(ZetaIcons.stagenow_sharp), + Icon(ZetaIcons.swipe_assist_sharp), + Icon(ZetaIcons.tekspeech_pro_sharp), + Icon(ZetaIcons.virtual_devices_sharp), + Icon(ZetaIcons.virtual_tether_sharp), + Icon(ZetaIcons.visibility_services_sharp), + Icon(ZetaIcons.voice_wedge_sharp), + Icon(ZetaIcons.workforce_connect_sharp), + Icon(ZetaIcons.workstation_connect_sharp), + Icon(ZetaIcons.zebra_designer_sharp), + Icon(ZetaIcons.zebra_onecare_sharp), + Icon(ZetaIcons.zebra_setup_utility_sharp), + Icon(ZetaIcons.zero_touch_sharp), + Icon(ZetaIcons.align_center_sharp), + Icon(ZetaIcons.align_horizontal_center_sharp), + Icon(ZetaIcons.align_horizontal_left_sharp), + Icon(ZetaIcons.align_horizontal_right_sharp), + Icon(ZetaIcons.align_left_sharp), + Icon(ZetaIcons.align_right_sharp), + Icon(ZetaIcons.align_vertical_bottom_sharp), + Icon(ZetaIcons.align_vertical_center_sharp), + Icon(ZetaIcons.align_vertical_top_sharp), + Icon(ZetaIcons.attach_sharp), + Icon(ZetaIcons.bold_sharp), + Icon(ZetaIcons.bullet_list_sharp), + Icon(ZetaIcons.checklist_sharp), + Icon(ZetaIcons.color_fill_sharp), + Icon(ZetaIcons.distribute_horizontal_sharp), + Icon(ZetaIcons.distribute_vertical_sharp), + Icon(ZetaIcons.edit_border_sharp), + Icon(ZetaIcons.edit_sharp), + Icon(ZetaIcons.font_size_decrease_sharp), + Icon(ZetaIcons.font_size_increase_sharp), + Icon(ZetaIcons.format_shapes_sharp), + Icon(ZetaIcons.indent_decrease_sharp), + Icon(ZetaIcons.indent_increase_sharp), + Icon(ZetaIcons.italic_sharp), + Icon(ZetaIcons.justify_sharp), + Icon(ZetaIcons.line_spacing_sharp), + Icon(ZetaIcons.link_sharp), + Icon(ZetaIcons.no_color_sharp), + Icon(ZetaIcons.numbered_list_sharp), + Icon(ZetaIcons.strikethrough_sharp), + Icon(ZetaIcons.text_color_sharp), + Icon(ZetaIcons.type_sharp), + Icon(ZetaIcons.underline_sharp), + Icon(ZetaIcons.barcode_bluetooth_sharp), + Icon(ZetaIcons.barcode_done_sharp), + Icon(ZetaIcons.barcode_image_scan_sharp), + Icon(ZetaIcons.barcode_qr_code_sharp), + Icon(ZetaIcons.barcode_sharp), + Icon(ZetaIcons.barcode_scanner_down_sharp), + Icon(ZetaIcons.barcode_settings_sharp), + Icon(ZetaIcons.calculator_sharp), + Icon(ZetaIcons.card_orientation_sharp), + Icon(ZetaIcons.card_with_chip_sharp), + Icon(ZetaIcons.certificate_sharp), + Icon(ZetaIcons.choices_sharp), + Icon(ZetaIcons.contactless_pay_sharp), + Icon(ZetaIcons.credit_card_swipe_sharp), + Icon(ZetaIcons.eas_sharp), + Icon(ZetaIcons.enterprise_diagnostics_sharp), + Icon(ZetaIcons.environmental_sharp), + Icon(ZetaIcons.factory_sharp), + Icon(ZetaIcons.freezer_sharp), + Icon(ZetaIcons.issue_audit_sharp), + Icon(ZetaIcons.performance_sharp), + Icon(ZetaIcons.planogram_sharp), + Icon(ZetaIcons.productivity_apps_sharp), + Icon(ZetaIcons.receipt_sharp), + Icon(ZetaIcons.retail_sharp), + Icon(ZetaIcons.road_map_sharp), + Icon(ZetaIcons.rules_sharp), + Icon(ZetaIcons.scan_rate_sharp), + Icon(ZetaIcons.shape_recognition_sharp), + Icon(ZetaIcons.solutions_sharp), + Icon(ZetaIcons.steps_sharp), + Icon(ZetaIcons.strategy_sharp), + Icon(ZetaIcons.tap_to_pay_sharp), + Icon(ZetaIcons.zero_scale_sharp), + Icon(ZetaIcons.attachment_sharp), + Icon(ZetaIcons.cloud_done_sharp), + Icon(ZetaIcons.cloud_download_sharp), + Icon(ZetaIcons.cloud_off_sharp), + Icon(ZetaIcons.cloud_outline_sharp), + Icon(ZetaIcons.cloud_sharp), + Icon(ZetaIcons.cloud_upload_sharp), + Icon(ZetaIcons.create_new_folder_sharp), + Icon(ZetaIcons.doc_attach_sharp), + Icon(ZetaIcons.downloading_sharp), + Icon(ZetaIcons.file_download_sharp), + Icon(ZetaIcons.file_upload_sharp), + Icon(ZetaIcons.finished_download_sharp), + Icon(ZetaIcons.folder_outline_sharp), + Icon(ZetaIcons.folder_sharp), + Icon(ZetaIcons.grid_view_sharp), + Icon(ZetaIcons.jpg_attach_sharp), + Icon(ZetaIcons.pdf_attach_sharp), + Icon(ZetaIcons.png_attach_sharp), + Icon(ZetaIcons.ppt_attach_sharp), + Icon(ZetaIcons.shared_folder_sharp), + Icon(ZetaIcons.upload_file_sharp), + Icon(ZetaIcons.cast_connected_sharp), + Icon(ZetaIcons.cast_sharp), + Icon(ZetaIcons.desktop_sharp), + Icon(ZetaIcons.device_settings_sharp), + Icon(ZetaIcons.devices_ecosystem_sharp), + Icon(ZetaIcons.headphones_sharp), + Icon(ZetaIcons.keyboard_sharp), + Icon(ZetaIcons.laptop_sharp), + Icon(ZetaIcons.memory_sharp), + Icon(ZetaIcons.monitor_sharp), + Icon(ZetaIcons.phone_android_sharp), + Icon(ZetaIcons.phone_iphone_sharp), + Icon(ZetaIcons.phonelink_sharp), + Icon(ZetaIcons.printer_sharp), + Icon(ZetaIcons.scanner_sharp), + Icon(ZetaIcons.security_sharp), + Icon(ZetaIcons.smart_phone_sharp), + Icon(ZetaIcons.speaker_sharp), + Icon(ZetaIcons.tablet_mac_sharp), + Icon(ZetaIcons.tablet_sharp), + Icon(ZetaIcons.tv_sharp), + Icon(ZetaIcons.video_play_sharp), + Icon(ZetaIcons.watch_sharp), + Icon(ZetaIcons.adjustments_sharp), + Icon(ZetaIcons.auto_sharp), + Icon(ZetaIcons.awb_sharp), + Icon(ZetaIcons.camera_sharp), + Icon(ZetaIcons.camera_shutter_sharp), + Icon(ZetaIcons.contrast_image_sharp), + Icon(ZetaIcons.crop_sharp), + Icon(ZetaIcons.eye_dropper_sharp), + Icon(ZetaIcons.flip_camera_sharp), + Icon(ZetaIcons.grid_off_sharp), + Icon(ZetaIcons.grid_on_sharp), + Icon(ZetaIcons.hdr_sharp), + Icon(ZetaIcons.image_library_sharp), + Icon(ZetaIcons.image_sharp), + Icon(ZetaIcons.iso_sharp), + Icon(ZetaIcons.portrait_sharp), + Icon(ZetaIcons.pro_sharp), + Icon(ZetaIcons.rotate_left_sharp), + Icon(ZetaIcons.rotate_right_sharp), + Icon(ZetaIcons.slide_show_sharp), + Icon(ZetaIcons.straighten_sharp), + Icon(ZetaIcons.timer_sharp), + Icon(ZetaIcons.visibility_image_sharp), + Icon(ZetaIcons.visibility_off_image_sharp), + Icon(ZetaIcons.wb_image_sharp), + Icon(ZetaIcons.wb_sharp), + Icon(ZetaIcons.bus_sharp), + Icon(ZetaIcons.cafe_sharp), + Icon(ZetaIcons.car_sharp), + Icon(ZetaIcons.flight_sharp), + Icon(ZetaIcons.layers_sharp), + Icon(ZetaIcons.light_rail_train_sharp), + Icon(ZetaIcons.local_shipping_sharp), + Icon(ZetaIcons.map_sharp), + Icon(ZetaIcons.my_location_sharp), + Icon(ZetaIcons.navigation_sharp), + Icon(ZetaIcons.near_me_sharp), + Icon(ZetaIcons.offer_sharp), + Icon(ZetaIcons.place_sharp), + Icon(ZetaIcons.ship_sharp), + Icon(ZetaIcons.taxi_sharp), + Icon(ZetaIcons.train_sharp), + Icon(ZetaIcons.world_sharp), + Icon(ZetaIcons.zoom_in_map_sharp), + Icon(ZetaIcons.zoom_out_map_sharp), + Icon(ZetaIcons.apps_sharp), + Icon(ZetaIcons.arrow_back_sharp), + Icon(ZetaIcons.arrow_down_sharp), + Icon(ZetaIcons.arrow_forward_sharp), + Icon(ZetaIcons.arrow_up_sharp), + Icon(ZetaIcons.cancel_outline_sharp), + Icon(ZetaIcons.cancel_sharp), + Icon(ZetaIcons.caret_down_sharp), + Icon(ZetaIcons.caret_left_sharp), + Icon(ZetaIcons.caret_right_sharp), + Icon(ZetaIcons.caret_sort_sharp), + Icon(ZetaIcons.caret_up_sharp), + Icon(ZetaIcons.check_sharp), + Icon(ZetaIcons.chevron_left_sharp), + Icon(ZetaIcons.chevron_right_sharp), + Icon(ZetaIcons.close_sharp), + Icon(ZetaIcons.columns_sharp), + Icon(ZetaIcons.dashboard_sharp), + Icon(ZetaIcons.drop_down_circle_sharp), + Icon(ZetaIcons.expand_less_sharp), + Icon(ZetaIcons.expand_more_sharp), + Icon(ZetaIcons.first_page_sharp), + Icon(ZetaIcons.full_screen_exit_sharp), + Icon(ZetaIcons.full_screen_sharp), + Icon(ZetaIcons.hamburger_menu_navigation_rail_sharp), + Icon(ZetaIcons.hamburger_menu_sharp), + Icon(ZetaIcons.hamburger_menu_thick_sharp), + Icon(ZetaIcons.help_outline_sharp), + Icon(ZetaIcons.help_sharp), + Icon(ZetaIcons.last_page_sharp), + Icon(ZetaIcons.list_alt_sharp), + Icon(ZetaIcons.list_sharp), + Icon(ZetaIcons.more_horizontal_sharp), + Icon(ZetaIcons.more_vertical_sharp), + Icon(ZetaIcons.refresh_sharp), + Icon(ZetaIcons.unfold_less_sharp), + Icon(ZetaIcons.unfold_more_sharp), + Icon(ZetaIcons.add_group_sharp), + Icon(ZetaIcons.add_person_sharp), + Icon(ZetaIcons.bad_mood_sharp), + Icon(ZetaIcons.blog_sharp), + Icon(ZetaIcons.dislike_sharp), + Icon(ZetaIcons.facebook_sharp), + Icon(ZetaIcons.group_sharp), + Icon(ZetaIcons.groups_sharp), + Icon(ZetaIcons.happy_sharp), + Icon(ZetaIcons.instagram_sharp), + Icon(ZetaIcons.ios_share_sharp), + Icon(ZetaIcons.like_sharp), + Icon(ZetaIcons.linkedin_sharp), + Icon(ZetaIcons.medium_sharp), + Icon(ZetaIcons.notifications_active_sharp), + Icon(ZetaIcons.notifications_outline_sharp), + Icon(ZetaIcons.notifications_sharp), + Icon(ZetaIcons.person_outline_sharp), + Icon(ZetaIcons.person_sharp), + Icon(ZetaIcons.remove_group_sharp), + Icon(ZetaIcons.remove_person_sharp), + Icon(ZetaIcons.sad_sharp), + Icon(ZetaIcons.satisfied_sharp), + Icon(ZetaIcons.share_sharp), + Icon(ZetaIcons.switch_user_sharp), + Icon(ZetaIcons.twitter_sharp), + Icon(ZetaIcons.very_satisfied_sharp), + Icon(ZetaIcons.world_map_sharp), + Icon(ZetaIcons.youtube_sharp), + Icon(ZetaIcons.check_box_empty_sharp), + Icon(ZetaIcons.check_box_sharp), + Icon(ZetaIcons.indeterminate_check_box_sharp), + Icon(ZetaIcons.radio_button_checked_sharp), + Icon(ZetaIcons.radio_button_unchecked_sharp), + Icon(ZetaIcons.star_half_sharp), + Icon(ZetaIcons.star_outline_sharp), + Icon(ZetaIcons.star_sharp), + Icon(ZetaIcons.toggle_off_sharp), + Icon(ZetaIcons.toggle_on_sharp), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock index a7342d64..cc2e46b8 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -379,7 +379,7 @@ packages: path: ".." relative: true source: path - version: "0.1.0+3" + version: "0.1.0+4" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/lib/src/assets/fonts/zeta-icons-round.ttf b/lib/src/assets/fonts/zeta-icons-round.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2ae882a0031348b787a87e85c35a8087867ff726 GIT binary patch literal 145320 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�e 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%0DsTTS8+`3Y><9xkqw&BMdSG;&AIyi2kM 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 Ua1Pb1HCthj{pDw literal 0 HcmV?d00001 diff --git a/lib/src/assets/fonts/zeta-icons-sharp.ttf b/lib/src/assets/fonts/zeta-icons-sharp.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f21be8b437af796464bc691b7fe48fc14f6b456d GIT binary patch literal 116564 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%0A^aOL-EmfY=G8K7c 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 `Jwe$))qx9h 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
    O%$K`Hj#piq0^j9m`-{G&1H zRhb&#iV#0yMQbj@Y^+C{h%*p@Pr1PJ^mfuIM2KW>5ZJ(*K;{5H0{Np}2|>sbeujz{ zsiNH($Lx-iYWXqnSgwy<5J4ZQTO(xdz!j?TZJbyuyA+Xk=mNo3l|k8yA)%K4F|2$e ziJ-)FU0zpTUw1h#fPOh-^B8aD_$uLfT1cu5mBPl0XofmoasTq@kQ_@hT|GutzFG?~ z^zV($YhrBI)IBmb+DF1hC~UM8DR0ao^vy;`KBNq7aG=!<$3r6}N&qDyNCxuHnvDYi zO30u^-B(;rLeLKxmUM$8va0x0+#xoeRYyz7y`?wQ*Hjh->WxPJlalJ%hVe_&7??Kh zJmO=C@P#e>%Lht3yY{ACE4Qh*!{%~#q90^Tf#UwW_fzC>Iml)_!lF;VbI&c%#ctQfR7Dr|H_uJ2oSu+4y?w_GGt3{oFzc>6 zca>@;YMZa`ogbAP+t|IRgsr$-w|2uO`wt)f#T!3QO@XU%*xJ)V(oTR+&0KUw#Mg&O zg>i}X6leo5`q$KO(zZ>T-hFoyJ0g^0iXiyQP5Ae&{MvZk8yQe-!hm`S-JA9*QC&#* z<6nr%_?%1G;J;emhW>}!n2JQ-zp9g1NF>TZ6$I-W($VCLq`1&4=3<{zFjkFF5YadB zwqI*!lHVpD`wy5WLH~uJh|(ZZQE|y z_2dpqb@r69cx#ji7C0^bYc)Fj*VCOPQ*#>P3`neTc=y(W!CUi_&06)oku^L`*Jv`O zrR1mO*(%~qT8<2uLQ>Tlxz-e4VarR)Pf1IdICX04+&kvBPMtb20XL`T+9t%C^_&}Z zxSMOVNN{P6uPA6O$qC&VxQAECrxh6wIF)!PJ;n!2W-zi{H=SI9m5^k32M5PexmV;= zB5|-Dt_@0<&d71u46hIV&p|qdRQSc9d>8-czHzWt3EgePzfR-6QfL~wm?J_EY`&7% zYvaRw_QQ(*7WsPc;;{t5@e1nn1;zT;(8wiCwqM0-e9hVsots z>mc!Kt#MiwhrDQ&@+a~qfl8k95Z}Z%Jt$9pj6EqIcW7U3;)esSM!7IBgY{$Q?C1AO zM`U*ab|eY;!O}PwMLgtKy%rY7@>B7Wi`Fggb;!rrlaGGoJN}D(k7X6GTZ3;>X_0sj zylo}51Da!e(?dKbyzviE8`*Cf`R!_})pc+OY`>`y6VZ3*iHV&G=Hv_yiw#TH7*eU~ z9tws+3UKO_&V)h5$dAVJ6~rUx9twlIup*3R;Zgm<(gl1i2K- zvVEQZ*Udu2E_=s(4nIj_jX0t=- z`aC^Zb3DC$PPf~W<@I?sIXn8wyZidQ4HXrg>iO~xPY-rza7Oe+*dfEZB08{3VsC^W z`&c_8y0G)B8|Qr&z2jm}t;AD4Jna&-WI?Vd$9P`s&Su=%EAF=A-A?Q>n*}eO0et%- zw&2ZGINKM|iQ`Vx=!xh-X^yCs?sntj!5Oc(wh3oCaCdn`w|L5nd8@#u^St}ZMello z@QmLi{9WW9`#VEkBBlXu(7`xnU`7^+s39}6Afb9Rivh)r1@eezHkJU_x+Ip&QdlZ> z+)f7{lF71Qr_N!y47t!*0sM7~STQR>F8@+i1{+`no5(6z6{SmJwX6<4qm$TV*1)E) zso-NMUHEi11NOGd*evV^G>0`KTlqXTpDkdpxv|A;30umRvE{6VwXzj#C0oT-vo&lj zyPU0K>k(?w#x^oLYiAwI!JMp-(wDlHtklo5|V~5yb zc00R+-O27^cVk!Jd)a;Le)etl06W4SWDl{2*>~6@>?r##dz3u}eEEI$IQs!RhTVgI z#GYWs*?+Jn*;DLk_G5N}J;P42XW4V?d1S)-2?9f2VlT5-*sJU{HpG5P?gs1)_9puo z`#F1yz0KZXzhLjO|3uQoU$I}a->~1Z_t^XF0~j(tWFN8Lvp=x^Vjr_VveWDnc82|l z{h58rK4X7je`Ws-jqBgo=a}O!*q7`d?4Rr`JI99E2peSqCbR$L5u9<3Jmc80mLt6j zH*h15;sHpU5kD6|d$syq4GTdOnFy<_&xbpUN9~6Q9PX^BH_5zl_h~v-up} z%;)lXd_G^m7xG1XF<-)$@@0HEZ{e+c1z*Wm!Pj&RU&}A&>-c)Ufw%FE+|Jv12X}BM z@8n&)o4Y_TH*+`d;l13$z5EL9<9^=9`}r2Wm2cw%d^^9A@8CQ6Rs3px4d2Cg^K1Ea zd=I~#-@y0sZ}A)XP5fp)$oKL6`~bg&ALO_4+xQ`VnBUIt;CJ%7_}%;-elNd|-_O6z zAK*v$gZv@>F#it1SB~=U@<;h&{CoWS{BiyRevJQ+|A;@qkMsZFPx7bu)BMN$1b>E~ z)u9y>;Dmazk;!_^l*cGLr0 z-R&M|!#iTmKN)(Z&)(bRGz7251q*FkozBh5!=aZe=R(H=PP@-Nkc1v~Y;Nmt`8wRr z;5g7*<1co>9DXuVIiLYFcDP;Mc8}fXuynXRs81bGtvE7u_^5Mj9k?FlaJrp+&bCgE z&$-3v3m&TX>y)ce4wv8U+U#tzcl3eo862LD{vKy<9|~K0-5$FmveV`6bNZ;AI;E)T zw)Z;p-7bHh$2Xwq_VhS4uHH_M7Bk>)hJ5)zypU=yBQM>g|%eu3oLz=jw23eIU$Rb$$$QM|YIp z+0pNF^$oO%!7})reSNswZ}JcHcBtLc_Idg{x-ETpj%sS7PMXG!`n{3;=rhKYI;#|Q z{ayzsKYnO1O#OZgg))N{Q4YRELq`S-v#ZkuINsv&yV_lDYK^C}Gct5&-sPs=kbkAw>V00^>{tLK6`IpTd$`N zukNtZEJkm&`+BK=>Rjv9V{JS2E((z1cRBzgUb@-bY4`ULkl-eVNgVi`G~!V`t`48a z+wJMaJau-)h94@6I5Kp~?6qSA)S=Oe1C!Tn$7Bd_H;b~`99W_313I6RevJOjE^k|} zb6cN9l)Qjdm!}`I*5~o64{NAw-r{mNJ!o_fSTWNUj~igB%%58B>F;w!s%13Ss22OZ z1{zeXS9e@Tx4o~ey}uopA~-aruybbchL}OW7(>0oWp{h+SVbNh+cvC|zJ6c3&f#$b zrx~3+Ksf{_7Nw+iO)HKJ059=IeUH=cw|6-$UR3MpZBrmMQ5n;AcfYgGe^Lw54 z%}$?1Igb_4XLoPbiX#I6-9u1qz5;;faX8!jKy7;Uz~J-y+d7?2hu%*w^f?TESC1%2 z{vN+YKt38ysL`RPVQBYkixtB$4hcnuPDv;l?7epPfZyfUW1;&zE{Cz*-m%&5wRboz z0)o&Gu)V!~z&TiYdiBWI;qeZ%0Y^A>z(QCw*znWdWd^nf(o-HVc>Dd`ZCJk=peawJ z&)Gvr0FAP##qr3|GVUxOhHl5A_qqoRemkBd+(HG7A0w{uV<~9*fhy2$G_TigX}9+Q zcM)pGVu}eKVak17SRQ)yL~Lj#f`b(oI;G4RZa0pdi){C~y1M&%F}cy8GHwzk+Wf9A z44W2}V?k4YeOOmU(6Y^KJ(xGW1AyJ(^c$Rg-A-Sxv(MD&rb@&`O}C@R6&X5?!a5aD z*yi=PfQ*BO(LEku6`*vV3mtY3M4=ual+EhPrQXgCZ7+QnA!4TR|bgSs4O~6N=tHU2_ z_X7d8p{pH$-!|YoXA~gB13jSI)CokSzQGoD zN_~OH=Z_0JyV*G)sA*hRkH3vZ4TJ@fo|u+2v<}nj>caiNH40_K^6~-`I3oqU6P?7& zbvoO+`mq4@0^B|Rs2&FvqS7V2(L{&TkIk+=vzSC84US&Bb?hKWzEXPn-F+@Ri?uGs z0;stMa103KJ=-KthcD9O6m@sHx~yKi3uD;T<_AI~Z0?WrIy!-@XmFyvo~>e#ogE-Y zp57QB*G|w4^v*xf)9!Jb#rOj&fp7vx(PXp%Y^a_@aU`Dh(2`bX&!_SFw)aHQN(5&i zpxon*RS$tNyLvr-0t~BqDm3TZx6MMR3&7)OqgKa@BcMJsXAGbKtGER;PaV2cI)?Ba zd{tW*7@AeuE5_9b#MkepyDfgONq|YG07pac$QUeaR!%vb+YIO{rq;97?BDA00-N}O z^ZG1(PT)GHvjd3A=ZW6p^7ZxG-Rc_ggR(2fePSKQg(y3Q(I-|oh!X*-0AVYwPD~(< z)gHys8Fi3@=c2Yd+kJMtg1{YgKsf~61xk0uDM#pRzqbu@OiV@OcBjvSeuJ4Y+X0`w zZ5;xn6P1H*P>k)sKxnpd-gd!xx3jY^;exXQtwk!Q=?;@p6sOfXKp-)}sJY$K*XQXu z|E%)9Smn8~dqKZ-0AcX>8i1X{)D8|0c*Bk1HVSTyN|7BNHy9j1o7+az*5_&mNpA~v zCNAu3uxgWFciTNahtn5JS{I}Btr#64L-Rty6gV7PITYVsS z9K2iS!YH~r^qcwt*PR1I%|L=d3bE)kwAKy11gvPdrMJJQ-ARj!I%A>sZw8F`JpEnW zk$qrrl-o3Y174>QRLbe2x~%QsU1_P0;YoAwi~|4=8$59J08|C-j}D$vd4Txfad4>+ zQwv(BR2$?^LF>ecNK9P^=oNT(2s`i&1*o9^V$DO?!HKOda3mewF0ZMBrdsfnPJKr= z0X4`SfmKJJ8>A1bc)*G=4aysBViidk_5=Zp3L*|e3KnNCR*$EbNPyj~??gS2AoQJ} zPJm~V%kS^UBJ4+fCh$vQnjpj(!6x>4x_tH?E7qf>pmD?N!1!(j>+J?G zM1sDwDQ__aD+G+01oBlM>U8zG{1B7J-Wa7k8)Rm6%Av8#=W?`daXGg}Zt`}il?u9` z)F0^u!3Y+;;1NXMEEpq#UZoC`@=C$Z0WKgRsQAn2(9j{+8UJQ1>u8lM2jR@BvN>%S zYX1O+wkNXNX?F--)^7+BTb&y;6gZ&=bOaCp3ETxxQ2Ae#=`^d{u=vrdgi#z(tzm0> zn<((D?NWQcAJfz6l(3X_3WJHU9)R=_qi~m~%uPI$t5@)tZoI_h1w-B?VcA6X+PAp6 z1TN6`g0pYyaca>qr%#Jv>j0OHdo_LbZ7!{-!K8|>wBpP`5ta@#v^FE{kXN^Y5$xEk z7745^%2_OK5;qOXQNI@hPWqZLKvoWctgx^Jw5vryl$5i|NGWCF{GpqnoBO?B!J%g% z{mB*}8!@_;;DLAu0t=+aUO$*~f45-%VrX8)dsLCrZMuqTPunbUjLL1`4TJQoH z$B>!=7+LVv&TT+iVJ9-W?LF=NzAkVs0I>eH(7?9Q3`C8;96$cBt*_gK4s<)+-r#^} z=)mZvbx7|v5Q!1e4;3I4_`>O=MH~kyByc1!tiRjT4U-q;mQfWP=0K2+Qy$$ab=V$DXWJ%<C+QBZ=&OQoLxz`%R!k zSmAA?lhOB~j5QpE@fc_uyV0oVVF0Z90lcff9lArIo`W#j=IrtI4JeEW38(QsyTj#y z;s6W}I4!!(=|~uN^8eIi2P*)AKoExMX!MRE#42JdiWT+r{fga&z3m+5J9VB7WmFqn zl5M2<2NQ;?Ys=pE>4A0PkBTKEwBSG#GKOF=gN7$4wy Date: Fri, 8 Dec 2023 15:11:07 +0200 Subject: [PATCH 07/41] Priority Pill (#28) * Priority Pill * [automated commit] lint format and import sort * remove unnecessary param * [automated commit] lint format and import sort --------- Co-authored-by: github-actions --- CHANGELOG.md | 50 ++++++++--- example/lib/home.dart | 2 + example/lib/pages/priority_pill_example.dart | 34 +++++++ example/pubspec.lock | 2 +- example/test/priority_pill_test.dart | 19 ++++ .../components/priority_pill_widgetbook.dart | 35 ++++++++ example/widgetbook/widgetbook.dart | 2 + lib/src/components/priority_pill.dart | 89 +++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 10 files changed, 224 insertions(+), 12 deletions(-) create mode 100644 example/lib/pages/priority_pill_example.dart create mode 100644 example/test/priority_pill_test.dart create mode 100644 example/widgetbook/components/priority_pill_widgetbook.dart create mode 100644 lib/src/components/priority_pill.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index fd695cd8..f688bfe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,32 @@ +## [0.1.0+6] - 2023-12-08 +### :flying_saucer: Other Changes +- [`2f21a18`](https://github.com/zebratechnologies/zeta-flutter/commit/2f21a18e30425fe91fe7bb0ee3c4df7ab8baca35) - add icons ([#24](https://github.com/zebratechnologies/zeta-flutter/pull/24)) + +* add icons + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`2442420`](https://github.com/zebratechnologies/zeta-flutter/commit/2442420da15739e538d50e14c2a18c63de8d6f96) - Priority Pill ([#28](https://github.com/zebratechnologies/zeta-flutter/pull/28)) + +* Priority Pill + +* [automated commit] lint format and import sort + +* remove unnecessary param + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + ## [0.1.0+5] - 2023-12-08 ### :flying_saucer: Other Changes - [`ef44d24`](https://github.com/zebratechnologies/zeta-flutter/commit/ef44d244589a7cc652a934f25a5122bbd1657c05) - status_label ([#25](https://github.com/zebratechnologies/zeta-flutter/pull/25)) @@ -35,15 +64,15 @@ Co-authored-by: github-actions Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`c90349b`](https://github.com/zebratechnologies/zeta-flutter/commit/c90349b104f3000956f821934b01dfd74f37a5e2) - add icons ([#24](https://github.com/zebratechnologies/zeta-flutter/pull/24)) -* add icons - -* [automated commit] lint format and import sort - -* [automated commit] lint format and import sort - ---------- - -Co-authored-by: Atanas Yordanov +* add icons + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -309,4 +338,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.0+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+12...0.1.0+2 [0.1.0+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+2...0.1.0+3 [0.1.0+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+3...0.1.0+4 -[0.1.0+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+4...0.1.0+5 \ No newline at end of file +[0.1.0+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+4...0.1.0+5 +[0.1.0+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+5...0.1.0+6 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 2b7ca782..752814e3 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/grid_example.dart'; +import 'package:zeta_example/pages/priority_pill_example.dart'; import 'package:zeta_example/pages/icons_example.dart'; import 'package:zeta_example/pages/spacing_example.dart'; import 'package:zeta_example/pages/status_label_example.dart'; @@ -23,6 +24,7 @@ final List components = [ Component(ColorExample.name, (context) => const ColorExample()), Component(IconsExample.name, (context) => const IconsExample()), Component(LabelExample.name, (context) => const LabelExample()), + Component(PriorityPillExample.name, (context) => const PriorityPillExample()), ]; class Home extends StatefulWidget { diff --git a/example/lib/pages/priority_pill_example.dart b/example/lib/pages/priority_pill_example.dart new file mode 100644 index 00000000..1584b8ed --- /dev/null +++ b/example/lib/pages/priority_pill_example.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; +import 'package:zeta_flutter/src/utils/enums.dart'; + +class PriorityPillExample extends StatelessWidget { + static const String name = 'PriorityPill'; + + const PriorityPillExample(); + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: 'PriorityPill', + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ZetaPriorityPill( + index: 1, + priority: 'Rounded', + borderType: BorderType.rounded, + ), + ZetaPriorityPill( + index: 2, + priority: 'Sharp', + ) + ], + ), + ), + ); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock index cc2e46b8..4db26e9c 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -379,7 +379,7 @@ packages: path: ".." relative: true source: path - version: "0.1.0+4" + version: "0.1.0+5" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/priority_pill_test.dart b/example/test/priority_pill_test.dart new file mode 100644 index 00000000..b2bd6557 --- /dev/null +++ b/example/test/priority_pill_test.dart @@ -0,0 +1,19 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import 'test_components.dart'; + +void main() { + testWidgets('Initializes with correct label and index', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaPriorityPill( + priority: 'High', + index: 2, + ), + ), + ); + expect(find.text('High'), findsOneWidget); + expect(find.text('2'), findsOneWidget); + }); +} diff --git a/example/widgetbook/components/priority_pill_widgetbook.dart b/example/widgetbook/components/priority_pill_widgetbook.dart new file mode 100644 index 00000000..89877ce7 --- /dev/null +++ b/example/widgetbook/components/priority_pill_widgetbook.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:zeta_flutter/src/utils/enums.dart'; + +WidgetbookComponent priorityPillWidgetBook() { + return WidgetbookComponent( + name: 'PriorityPill', + useCases: [ + WidgetbookUseCase( + name: 'Priority Pill', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ZetaPriorityPill( + index: 1, + priority: 'Priority', + borderType: BorderType.rounded, + ), + SizedBox(height: 50), + ZetaPriorityPill( + index: 2, + priority: 'Priority', + ) + ], + ), + ), + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index c9283044..dc0009f9 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -4,6 +4,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; import 'components/color_widgetbook.dart'; import 'components/grid_widgetbook.dart'; +import 'components/priority_pill_widgetbook.dart'; import 'components/spacing_widgetbook.dart'; import 'components/status_label_widgetbook.dart'; import 'components/typography_widgetbook.dart'; @@ -26,6 +27,7 @@ class HotReload extends StatelessWidget { textWidgetBook(), colorWidgetBook(), statusLabelWidgetBook(), + priorityPillWidgetBook() ], ), ], diff --git a/lib/src/components/priority_pill.dart b/lib/src/components/priority_pill.dart new file mode 100644 index 00000000..a39f8ea2 --- /dev/null +++ b/lib/src/components/priority_pill.dart @@ -0,0 +1,89 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; +import '../utils/enums.dart'; + +///Zeta Priority Pill +class ZetaPriorityPill extends StatelessWidget { + ///Constructs [ZetaPriorityPill] + const ZetaPriorityPill({ + required this.index, + required this.priority, + this.borderType = BorderType.sharp, + super.key, + }); + + ///Border type of the badge + final BorderType borderType; + + ///Priority number + final int index; + + ///Priority label + final String priority; + + bool get _isBorderRounded => borderType == BorderType.rounded; + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + return DecoratedBox( + decoration: _buildBoxDecoration(theme), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + _buildIndexContainer(theme), + _buildPriorityText(), + ], + ), + ); + } + + BoxDecoration _buildBoxDecoration(Zeta theme) { + return BoxDecoration( + borderRadius: BorderRadius.circular( + _isBorderRounded ? Dimensions.l : Dimensions.x0, + ), + color: theme.colors.blue.shade10, + ); + } + + Widget _buildIndexContainer(Zeta theme) { + return Container( + alignment: Alignment.center, + height: Dimensions.l, + width: Dimensions.l, + decoration: BoxDecoration( + shape: _isBorderRounded ? BoxShape.circle : BoxShape.rectangle, + color: theme.colors.blue.shade60, + ), + child: Text( + '$index', + style: ZetaText.zetaBodyMedium.apply(color: theme.colors.white), + ), + ); + } + + Widget _buildPriorityText() { + return Flexible( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: Dimensions.s), + child: Text( + priority, + style: ZetaText.zetaBodyMedium, + overflow: TextOverflow.ellipsis, + ), + ), + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('borderType', borderType)) + ..add(IntProperty('index', index)) + ..add(StringProperty('priority', priority)); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 900c4e6b..75be6f88 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -2,6 +2,7 @@ library zeta_flutter; export 'src/components/grid.dart'; +export 'src/components/priority_pill.dart'; export 'src/components/spacing.dart'; export 'src/components/status_label.dart'; export 'src/components/text.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index e1b9af82..23a774f1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.0+5 +version: 0.1.0+6 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. From 36f72c1df09fecc9d3eeb6dbf1bbf889493529c0 Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Mon, 11 Dec 2023 12:21:01 +0200 Subject: [PATCH 08/41] Component indicator (#30) * add icons * [automated commit] lint format and import sort * create ZetaIndicator component with examples * fix value * add more comments * add widgetbook * [automated commit] lint format and import sort --------- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions --- CHANGELOG.md | 56 +++- example/lib/home.dart | 2 + example/lib/pages/indicator_example.dart | 120 +++++++++ example/pubspec.lock | 2 +- .../components/indicator_widgetbook.dart | 25 ++ example/widgetbook/widgetbook.dart | 2 + lib/src/components/indicator.dart | 253 ++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 9 files changed, 452 insertions(+), 11 deletions(-) create mode 100644 example/lib/pages/indicator_example.dart create mode 100644 example/widgetbook/components/indicator_widgetbook.dart create mode 100644 lib/src/components/indicator.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index f688bfe1..ec540fa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,29 +1,66 @@ -## [0.1.0+6] - 2023-12-08 +## [0.1.0+7] - 2023-12-11 ### :flying_saucer: Other Changes -- [`2f21a18`](https://github.com/zebratechnologies/zeta-flutter/commit/2f21a18e30425fe91fe7bb0ee3c4df7ab8baca35) - add icons ([#24](https://github.com/zebratechnologies/zeta-flutter/pull/24)) +- [`19e7d93`](https://github.com/zebratechnologies/zeta-flutter/commit/19e7d933456938d473f1f5c6ef2696e02349e196) - Priority Pill ([#28](https://github.com/zebratechnologies/zeta-flutter/pull/28)) -* add icons +* Priority Pill * [automated commit] lint format and import sort +* remove unnecessary param + * [automated commit] lint format and import sort --------- -Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* -- [`2442420`](https://github.com/zebratechnologies/zeta-flutter/commit/2442420da15739e538d50e14c2a18c63de8d6f96) - Priority Pill ([#28](https://github.com/zebratechnologies/zeta-flutter/pull/28)) +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`fe4fe8d`](https://github.com/zebratechnologies/zeta-flutter/commit/fe4fe8d088fddf9443ce5810a1d2c068b13c75d9) - Component indicator ([#30](https://github.com/zebratechnologies/zeta-flutter/pull/30)) -* Priority Pill +* add icons * [automated commit] lint format and import sort -* remove unnecessary param +* create ZetaIndicator component with examples + +* fix value + +* add more comments + +* add widgetbook * [automated commit] lint format and import sort --------- +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + +## [0.1.0+6] - 2023-12-08 +### :flying_saucer: Other Changes +- [`2f21a18`](https://github.com/zebratechnologies/zeta-flutter/commit/2f21a18e30425fe91fe7bb0ee3c4df7ab8baca35) - add icons ([#24](https://github.com/zebratechnologies/zeta-flutter/pull/24)) + +* add icons + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`2442420`](https://github.com/zebratechnologies/zeta-flutter/commit/2442420da15739e538d50e14c2a18c63de8d6f96) - Priority Pill ([#28](https://github.com/zebratechnologies/zeta-flutter/pull/28)) + +* Priority Pill + +* [automated commit] lint format and import sort + +* remove unnecessary param + +* [automated commit] lint format and import sort + +--------- + Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* @@ -339,4 +376,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.0+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+2...0.1.0+3 [0.1.0+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+3...0.1.0+4 [0.1.0+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+4...0.1.0+5 -[0.1.0+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+5...0.1.0+6 \ No newline at end of file +[0.1.0+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+5...0.1.0+6 +[0.1.0+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+6...0.1.0+7 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 752814e3..8420f2ce 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -4,6 +4,7 @@ import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/grid_example.dart'; import 'package:zeta_example/pages/priority_pill_example.dart'; import 'package:zeta_example/pages/icons_example.dart'; +import 'package:zeta_example/pages/indicator_example.dart'; import 'package:zeta_example/pages/spacing_example.dart'; import 'package:zeta_example/pages/status_label_example.dart'; import 'package:zeta_example/pages/typography_example.dart'; @@ -23,6 +24,7 @@ final List components = [ Component(TypographyExample.name, (context) => const TypographyExample()), Component(ColorExample.name, (context) => const ColorExample()), Component(IconsExample.name, (context) => const IconsExample()), + Component(IndicatorExample.name, (context) => const IndicatorExample()), Component(LabelExample.name, (context) => const LabelExample()), Component(PriorityPillExample.name, (context) => const PriorityPillExample()), ]; diff --git a/example/lib/pages/indicator_example.dart b/example/lib/pages/indicator_example.dart new file mode 100644 index 00000000..2cd13726 --- /dev/null +++ b/example/lib/pages/indicator_example.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class IndicatorExample extends StatelessWidget { + static const String name = 'Indicator'; + + const IndicatorExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: IndicatorExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + indicatorIconExample, + const SizedBox(height: 25), + indicatorNotificationExample, + ], + ), + ), + ); + }, + ); + } + + static Widget get indicatorIconExample => Column( + children: [ + Text( + 'ZetaIndicator.icon', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Rounded', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + Row( + children: [ + ZetaIndicator.icon(), + const SizedBox(width: 20), + ZetaIndicator.icon( + size: ZetaIndicatorSize.medium, + ), + const SizedBox(width: 20), + ZetaIndicator.icon( + size: ZetaIndicatorSize.small, + ), + ], + ), + ], + ), + const SizedBox(width: 50), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Sharp', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + Row( + children: [ + ZetaIndicator.icon(sharp: true), + const SizedBox(width: 20), + ZetaIndicator.icon( + size: ZetaIndicatorSize.medium, + sharp: true, + ), + const SizedBox(width: 20), + ZetaIndicator.icon( + size: ZetaIndicatorSize.small, + ), + ], + ), + ], + ), + ], + ), + ], + ); + + static Widget get indicatorNotificationExample => Column( + children: [ + Text( + 'ZetaIndicator.notification', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + ZetaIndicator.notification( + value: 3, + ), + const SizedBox(width: 20), + ZetaIndicator.notification( + size: ZetaIndicatorSize.medium, + value: 3, + ), + const SizedBox(width: 20), + ZetaIndicator.notification( + size: ZetaIndicatorSize.small, + value: 3, + ), + ], + ), + ], + ); +} diff --git a/example/pubspec.lock b/example/pubspec.lock index 4db26e9c..672af97f 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -379,7 +379,7 @@ packages: path: ".." relative: true source: path - version: "0.1.0+5" + version: "0.1.0+6" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/widgetbook/components/indicator_widgetbook.dart b/example/widgetbook/components/indicator_widgetbook.dart new file mode 100644 index 00000000..e73eadbe --- /dev/null +++ b/example/widgetbook/components/indicator_widgetbook.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/indicator_example.dart'; + +WidgetbookComponent indicatorWidgetBook() { + return WidgetbookComponent( + name: 'Indicator', + useCases: [ + WidgetbookUseCase( + name: 'Icon', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: IndicatorExample.indicatorIconExample, + ), + ), + WidgetbookUseCase( + name: 'Notification', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: IndicatorExample.indicatorNotificationExample, + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index dc0009f9..9fc66b23 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -4,6 +4,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; import 'components/color_widgetbook.dart'; import 'components/grid_widgetbook.dart'; +import 'components/indicator_widgetbook.dart'; import 'components/priority_pill_widgetbook.dart'; import 'components/spacing_widgetbook.dart'; import 'components/status_label_widgetbook.dart'; @@ -27,6 +28,7 @@ class HotReload extends StatelessWidget { textWidgetBook(), colorWidgetBook(), statusLabelWidgetBook(), + indicatorWidgetBook(), priorityPillWidgetBook() ], ), diff --git a/lib/src/components/indicator.dart b/lib/src/components/indicator.dart new file mode 100644 index 00000000..fc0df803 --- /dev/null +++ b/lib/src/components/indicator.dart @@ -0,0 +1,253 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '../../zeta_flutter.dart'; + +/// [ZetaIndicator] type +enum ZetaIndicatorType { + /// [icon] shows an icon + icon, + + /// [notification] shows a number provided with the `value` parameter + notification, +} + +/// [ZetaIndicator] size +enum ZetaIndicatorSize { + /// [large] 16 pixels + large, + + /// [medium] 12 pixels + medium, + + /// [small] 8 pixels + small, +} + +/// ZetaIndicator component +class ZetaIndicator extends StatelessWidget { + /// Constructor for [ZetaIndicator] + ZetaIndicator({ + super.key, + required this.type, + this.size = ZetaIndicatorSize.large, + this.icon, + this.sharp = false, + this.value, + this.backgroundColor, + this.foregroundColor, + this.borderColor, + }) { + _sizePixels = getSizePixels(size, type); + } + + /// Constructor for [ZetaIndicator] of type `icon` + factory ZetaIndicator.icon({ + ZetaIndicatorSize size = ZetaIndicatorSize.large, + Color? backgroundColor, + Color? foregroundColor, + Color? borderColor, + Icon? icon, + bool sharp = false, + }) => + ZetaIndicator( + type: ZetaIndicatorType.icon, + size: size, + backgroundColor: backgroundColor, + foregroundColor: foregroundColor, + borderColor: borderColor, + icon: icon, + sharp: sharp, + ); + + /// Constructor for [ZetaIndicator] of type `icon` + factory ZetaIndicator.notification({ + ZetaIndicatorSize size = ZetaIndicatorSize.large, + Color? backgroundColor, + Color? foregroundColor, + Color? borderColor, + int? value, + }) => + ZetaIndicator( + type: ZetaIndicatorType.notification, + size: size, + backgroundColor: backgroundColor, + foregroundColor: foregroundColor, + borderColor: borderColor, + value: value, + ); + + /// The type of the [ZetaIndicator] - icon or notification + final ZetaIndicatorType type; + + /// The size of the [ZetaIndicator] + final ZetaIndicatorSize size; + + /// Background color + final Color? backgroundColor; + + /// Foreground color + final Color? foregroundColor; + + /// Border color + final Color? borderColor; + + /// Indicator icon, default: `ZetaIcons.star_round` + final Icon? icon; + + /// Determines if the default icon should be sharp: `ZetaIcons.star_sharp`. + /// Default is `false`. + /// Not taken into account, if [icon] is provided. + final bool sharp; + + /// Value for the type `notification` + final int? value; + + late final double _sizePixels; + + @override + Widget build(BuildContext context) { + final zetaColors = Zeta.of(context).colors; + + return Container( + width: _sizePixels + 4, + height: _sizePixels + 4, + decoration: BoxDecoration( + color: backgroundColor ?? (type == ZetaIndicatorType.icon ? zetaColors.blue : zetaColors.negative), + border: Border.all( + color: borderColor ?? zetaColors.surfacePrimary, + width: 2, + ), + borderRadius: BorderRadius.circular(20), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + clipBehavior: Clip.hardEdge, + child: size == ZetaIndicatorSize.small + ? null + : _InnerContent( + type: type, + size: size, + sizePixels: _sizePixels, + icon: icon, + sharp: sharp, + value: value, + foregroundColor: foregroundColor, + ), + ), + ); + } + + /// Returns the size of [ZetaIndicatorSize] in pixels + static double getSizePixels(ZetaIndicatorSize size, ZetaIndicatorType type) { + switch (size) { + case ZetaIndicatorSize.large: + return 16; + case ZetaIndicatorSize.medium: + return type == ZetaIndicatorType.icon ? 12 : 14; + case ZetaIndicatorSize.small: + return 8; + } + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', type)) + ..add(DiagnosticsProperty('size', size)) + ..add(DiagnosticsProperty('value', value)) + ..add(DiagnosticsProperty('icon', icon)) + ..add(DiagnosticsProperty('sharp', sharp)) + ..add(DiagnosticsProperty('backgroundColor', backgroundColor)) + ..add(DiagnosticsProperty('foregroundColor', foregroundColor)) + ..add(DiagnosticsProperty('borderColor', borderColor)); + } +} + +class _InnerContent extends StatelessWidget { + const _InnerContent({ + required this.type, + required this.size, + required this.sizePixels, + this.icon, + this.sharp = false, + this.value, + this.foregroundColor, + }); + + final ZetaIndicatorType type; + final ZetaIndicatorSize size; + final double sizePixels; + final Icon? icon; + final bool sharp; + final int? value; + final Color? foregroundColor; + + @override + Widget build(BuildContext context) { + final defaultColor = Zeta.of(context).colors.white; + switch (type) { + case ZetaIndicatorType.icon: + final iconSize = _getIconSize(size); + return Center( + child: IconTheme( + data: IconThemeData( + color: foregroundColor ?? defaultColor, + size: iconSize, + ), + child: icon ?? Icon(sharp ? ZetaIcons.star_sharp : ZetaIcons.star_round), + ), + ); + case ZetaIndicatorType.notification: + final strVal = value == null ? '' : value!.abs().toString(); + final fontSize = _getFontSize(size); + return Center( + child: Text( + strVal.length > 1 ? '9+' : strVal, + textAlign: strVal.length == 1 ? null : TextAlign.right, + style: TextStyle( + fontSize: fontSize, + height: fontSize * .067, + letterSpacing: -0.5, + color: foregroundColor ?? defaultColor, + ), + ), + ); + } + } + + double _getIconSize(ZetaIndicatorSize size) { + switch (size) { + case ZetaIndicatorSize.large: + return 11; + case ZetaIndicatorSize.medium: + return 8; + case ZetaIndicatorSize.small: + return 1; + } + } + + double _getFontSize(ZetaIndicatorSize size) { + switch (size) { + case ZetaIndicatorSize.large: + return 12; + case ZetaIndicatorSize.medium: + return 11; + case ZetaIndicatorSize.small: + return 1; + } + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', type)) + ..add(DiagnosticsProperty('size', size)) + ..add(DiagnosticsProperty('sizePixels', sizePixels)) + ..add(DiagnosticsProperty('value', value)) + ..add(DiagnosticsProperty('icon', icon)) + ..add(DiagnosticsProperty('sharp', sharp)) + ..add(DiagnosticsProperty('foregroundColor', foregroundColor)); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 75be6f88..f7c9d73d 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -2,6 +2,7 @@ library zeta_flutter; export 'src/components/grid.dart'; +export 'src/components/indicator.dart'; export 'src/components/priority_pill.dart'; export 'src/components/spacing.dart'; export 'src/components/status_label.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 23a774f1..69852d48 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.0+6 +version: 0.1.0+7 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. From b97fd3bd881a85c8d4ee4f5ea5856e7a8ebf2d09 Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Mon, 11 Dec 2023 16:30:31 +0200 Subject: [PATCH 09/41] Badge (#29) * initial * Badge * fix test * [automated commit] lint format and import sort * change default border type * fix test * [automated commit] lint format and import sort * [automated commit] lint format and import sort * [automated commit] lint format and import sort * fix example * fix sizing * add foreground colors * [automated commit] lint format and import sort --------- Co-authored-by: github-actions --- CHANGELOG.md | 82 ++++++++++-- example/lib/home.dart | 2 + example/lib/pages/badge_example.dart | 47 +++++++ example/lib/pages/status_label_example.dart | 18 +-- example/pubspec.lock | 2 +- example/test/badge_test.dart | 25 ++++ .../components/badge_widgetbook.dart | 62 +++++++++ .../components/status_label_widgetbook.dart | 13 +- example/widgetbook/widgetbook.dart | 2 + lib/src/components/badge.dart | 122 ++++++++++++++++++ lib/src/components/status_label.dart | 43 ++---- lib/src/utils/enums.dart | 21 +++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 14 files changed, 380 insertions(+), 62 deletions(-) create mode 100644 example/lib/pages/badge_example.dart create mode 100644 example/test/badge_test.dart create mode 100644 example/widgetbook/components/badge_widgetbook.dart create mode 100644 lib/src/components/badge.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index ec540fa1..24e03fa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,37 +1,92 @@ -## [0.1.0+7] - 2023-12-11 +## [0.1.0+8] - 2023-12-11 ### :flying_saucer: Other Changes -- [`19e7d93`](https://github.com/zebratechnologies/zeta-flutter/commit/19e7d933456938d473f1f5c6ef2696e02349e196) - Priority Pill ([#28](https://github.com/zebratechnologies/zeta-flutter/pull/28)) +- [`36f72c1`](https://github.com/zebratechnologies/zeta-flutter/commit/36f72c1df09fecc9d3eeb6dbf1bbf889493529c0) - Component indicator ([#30](https://github.com/zebratechnologies/zeta-flutter/pull/30)) -* Priority Pill +* add icons * [automated commit] lint format and import sort -* remove unnecessary param +* create ZetaIndicator component with examples + +* fix value + +* add more comments + +* add widgetbook * [automated commit] lint format and import sort --------- -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* -- [`fe4fe8d`](https://github.com/zebratechnologies/zeta-flutter/commit/fe4fe8d088fddf9443ce5810a1d2c068b13c75d9) - Component indicator ([#30](https://github.com/zebratechnologies/zeta-flutter/pull/30)) +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`895bbfa`](https://github.com/zebratechnologies/zeta-flutter/commit/895bbfa876c7fea331d6bdb14c77e25632aab28d) - Badge ([#29](https://github.com/zebratechnologies/zeta-flutter/pull/29)) -* add icons +* initial + +* Badge + +* fix test * [automated commit] lint format and import sort -* create ZetaIndicator component with examples +* change default border type -* fix value +* fix test -* add more comments +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* fix example + +* fix sizing -* add widgetbook +* add foreground colors * [automated commit] lint format and import sort --------- -Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + +## [0.1.0+7] - 2023-12-11 +### :flying_saucer: Other Changes +- [`19e7d93`](https://github.com/zebratechnologies/zeta-flutter/commit/19e7d933456938d473f1f5c6ef2696e02349e196) - Priority Pill ([#28](https://github.com/zebratechnologies/zeta-flutter/pull/28)) + +* Priority Pill + +* [automated commit] lint format and import sort + +* remove unnecessary param + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`fe4fe8d`](https://github.com/zebratechnologies/zeta-flutter/commit/fe4fe8d088fddf9443ce5810a1d2c068b13c75d9) - Component indicator ([#30](https://github.com/zebratechnologies/zeta-flutter/pull/30)) + +* add icons + +* [automated commit] lint format and import sort + +* create ZetaIndicator component with examples + +* fix value + +* add more comments + +* add widgetbook + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -377,4 +432,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.0+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+3...0.1.0+4 [0.1.0+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+4...0.1.0+5 [0.1.0+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+5...0.1.0+6 -[0.1.0+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+6...0.1.0+7 \ No newline at end of file +[0.1.0+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+6...0.1.0+7 +[0.1.0+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+7...0.1.0+8 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 8420f2ce..ba51d227 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:zeta_example/pages/badge_example.dart'; import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/grid_example.dart'; import 'package:zeta_example/pages/priority_pill_example.dart'; @@ -26,6 +27,7 @@ final List components = [ Component(IconsExample.name, (context) => const IconsExample()), Component(IndicatorExample.name, (context) => const IndicatorExample()), Component(LabelExample.name, (context) => const LabelExample()), + Component(BadgeExample.name, (context) => const BadgeExample()), Component(PriorityPillExample.name, (context) => const PriorityPillExample()), ]; diff --git a/example/lib/pages/badge_example.dart b/example/lib/pages/badge_example.dart new file mode 100644 index 00000000..2d785973 --- /dev/null +++ b/example/lib/pages/badge_example.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:zeta_flutter/src/utils/enums.dart'; + +import '../widgets.dart'; + +class BadgeExample extends StatelessWidget { + static const String name = 'Badge'; + + const BadgeExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: BadgeExample.name, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + badgeExampleRow(WidgetSeverity.info), + badgeExampleRow(WidgetSeverity.positive), + badgeExampleRow(WidgetSeverity.warning), + badgeExampleRow(WidgetSeverity.negative), + badgeExampleRow(WidgetSeverity.neutral), + ], + ), + ), + ); + } +} + +Widget badgeExampleRow(WidgetSeverity type) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ZetaBadge( + label: 'Label', + severity: type, + borderType: BorderType.sharp, + ), + ZetaBadge( + label: 'Label', + severity: type, + ), + ]); +} diff --git a/example/lib/pages/status_label_example.dart b/example/lib/pages/status_label_example.dart index e0d1bef4..4b94cca4 100644 --- a/example/lib/pages/status_label_example.dart +++ b/example/lib/pages/status_label_example.dart @@ -17,13 +17,13 @@ class LabelExample extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - statusLabelExampleRow(ZetaStatusLabelType.neutral), - statusLabelExampleRow(ZetaStatusLabelType.info), - statusLabelExampleRow(ZetaStatusLabelType.positive), - statusLabelExampleRow(ZetaStatusLabelType.warning), - statusLabelExampleRow(ZetaStatusLabelType.negative), + statusLabelExampleRow(WidgetSeverity.neutral), + statusLabelExampleRow(WidgetSeverity.info), + statusLabelExampleRow(WidgetSeverity.positive), + statusLabelExampleRow(WidgetSeverity.warning), + statusLabelExampleRow(WidgetSeverity.negative), statusLabelExampleRow( - ZetaStatusLabelType.custom, + WidgetSeverity.custom, colors: ZetaStatusLabelColors(accentColor: Colors.blue, backgroundColor: Colors.blue.shade50), ), ], @@ -33,20 +33,20 @@ class LabelExample extends StatelessWidget { } } -Widget statusLabelExampleRow(ZetaStatusLabelType type, {ZetaStatusLabelColors? colors}) { +Widget statusLabelExampleRow(WidgetSeverity type, {ZetaStatusLabelColors? colors}) { return Padding( padding: EdgeInsets.all(10), child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ ZetaStatusLabel( label: 'Label', - labelType: type, + severity: type, isDefaultIcon: false, customColors: colors, ), ZetaStatusLabel( label: 'Label', - labelType: type, + severity: type, borderType: BorderType.rounded, customColors: colors, ), diff --git a/example/pubspec.lock b/example/pubspec.lock index 672af97f..0f9ebfcd 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -379,7 +379,7 @@ packages: path: ".." relative: true source: path - version: "0.1.0+6" + version: "0.1.0+7" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/badge_test.dart b/example/test/badge_test.dart new file mode 100644 index 00000000..72c57265 --- /dev/null +++ b/example/test/badge_test.dart @@ -0,0 +1,25 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:zeta_flutter/src/utils/enums.dart'; + +import 'test_components.dart'; + +void main() { + testWidgets('Initializes with correct parameters', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaBadge( + label: 'Test Label', + severity: WidgetSeverity.warning, + ), + ), + ); + + final zetaBadgeFinder = find.byType(ZetaBadge); + final ZetaBadge badge = tester.firstWidget(zetaBadgeFinder); + + expect(badge.borderType, BorderType.rounded); + expect(badge.label, 'Test Label'); + expect(badge.severity, WidgetSeverity.warning); + }); +} diff --git a/example/widgetbook/components/badge_widgetbook.dart b/example/widgetbook/components/badge_widgetbook.dart new file mode 100644 index 00000000..cf5a0544 --- /dev/null +++ b/example/widgetbook/components/badge_widgetbook.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_flutter/src/utils/enums.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent badgeWidgetBook() { + return WidgetbookComponent( + name: 'Badge', + useCases: [ + WidgetbookUseCase( + name: 'Badge Rounded', + builder: (context) => SingleChildScrollView( + child: Column( + children: [ + _badgeExampleRow(WidgetSeverity.info), + _badgeExampleRow(WidgetSeverity.positive), + _badgeExampleRow(WidgetSeverity.warning), + _badgeExampleRow(WidgetSeverity.negative), + _badgeExampleRow(WidgetSeverity.neutral), + _badgeExampleRow(WidgetSeverity.custom, customColor: Colors.blue), + ], + ), + ), + ), + WidgetbookUseCase( + name: 'Badge Sharp', + builder: (context) => SingleChildScrollView( + child: Column( + children: [ + _badgeExampleRow(WidgetSeverity.info, isRounded: false), + _badgeExampleRow(WidgetSeverity.positive, isRounded: false), + _badgeExampleRow(WidgetSeverity.warning, isRounded: false), + _badgeExampleRow(WidgetSeverity.negative, isRounded: false), + _badgeExampleRow(WidgetSeverity.neutral, isRounded: false), + _badgeExampleRow( + WidgetSeverity.custom, + customColor: Colors.blue, + isRounded: false, + ), + ], + ), + ), + ), + ], + ); +} + +Widget _badgeExampleRow(WidgetSeverity type, {bool isRounded = true, Color? customColor}) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.symmetric(vertical: 10), + child: ZetaBadge( + label: 'Label', + severity: type, + customColor: customColor, + borderType: isRounded ? BorderType.rounded : BorderType.sharp, + )), + ]); +} diff --git a/example/widgetbook/components/status_label_widgetbook.dart b/example/widgetbook/components/status_label_widgetbook.dart index 43b61601..976f182d 100644 --- a/example/widgetbook/components/status_label_widgetbook.dart +++ b/example/widgetbook/components/status_label_widgetbook.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_example/pages/status_label_example.dart'; +import 'package:zeta_flutter/src/utils/enums.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; WidgetbookComponent statusLabelWidgetBook() { @@ -12,13 +13,13 @@ WidgetbookComponent statusLabelWidgetBook() { builder: (context) => SingleChildScrollView( child: Column( children: [ - statusLabelExampleRow(ZetaStatusLabelType.neutral), - statusLabelExampleRow(ZetaStatusLabelType.info), - statusLabelExampleRow(ZetaStatusLabelType.positive), - statusLabelExampleRow(ZetaStatusLabelType.warning), - statusLabelExampleRow(ZetaStatusLabelType.negative), + statusLabelExampleRow(WidgetSeverity.neutral), + statusLabelExampleRow(WidgetSeverity.info), + statusLabelExampleRow(WidgetSeverity.positive), + statusLabelExampleRow(WidgetSeverity.warning), + statusLabelExampleRow(WidgetSeverity.negative), statusLabelExampleRow( - ZetaStatusLabelType.custom, + WidgetSeverity.custom, colors: ZetaStatusLabelColors(accentColor: Colors.blue, backgroundColor: Colors.blue.shade50), ), ], diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 9fc66b23..da02347e 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; +import 'components/badge_widgetbook.dart'; import 'components/color_widgetbook.dart'; import 'components/grid_widgetbook.dart'; import 'components/indicator_widgetbook.dart'; @@ -28,6 +29,7 @@ class HotReload extends StatelessWidget { textWidgetBook(), colorWidgetBook(), statusLabelWidgetBook(), + badgeWidgetBook(), indicatorWidgetBook(), priorityPillWidgetBook() ], diff --git a/lib/src/components/badge.dart b/lib/src/components/badge.dart new file mode 100644 index 00000000..f776f1bc --- /dev/null +++ b/lib/src/components/badge.dart @@ -0,0 +1,122 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; +import '../utils/enums.dart'; + +///Zeta Badge +class ZetaBadge extends StatelessWidget { + ///Constructs [ZetaBadge] + const ZetaBadge({ + required this.label, + this.severity = WidgetSeverity.info, + this.borderType = BorderType.rounded, + this.badgeSize = const Size(Dimensions.x9, Dimensions.x5), + this.customColor, + super.key, + }); + + ///The shape of the badge + /// + /// Defaults to rounded + final BorderType borderType; + + ///Indicates the severity of the badge + ///If set to "custom", [customColor] should be picked + ///Defaults to "info" + final WidgetSeverity severity; + + ///Label of the badge + final String label; + + ///The size of the badge + final Size badgeSize; + + ///Custom color of the badge + final Color? customColor; + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + return Container( + height: badgeSize.height, + constraints: BoxConstraints(minWidth: badgeSize.width), + decoration: _buildBadgeDecoration(theme), + child: Center( + child: _buildBadgeContent(theme), + ), + ); + } + + BoxDecoration _buildBadgeDecoration(Zeta theme) { + return BoxDecoration( + color: _badgeBackgroundColor(theme), + borderRadius: BorderRadius.circular( + borderType == BorderType.rounded ? Dimensions.x1 : 0.0, + ), + ); + } + + Widget _buildBadgeContent(Zeta theme) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Padding( + padding: const EdgeInsets.fromLTRB(4, 2, 4, 2), + child: Text( + label, + style: ZetaText.zetaLabelSmall.apply(color: _badgeForegroundColor(theme)), + overflow: TextOverflow.ellipsis, + ), + ), + ), + ], + ); + } + + Color _badgeBackgroundColor(Zeta theme) { + switch (severity) { + case WidgetSeverity.info: + return theme.colors.purple; + case WidgetSeverity.positive: + return theme.colors.green; + case WidgetSeverity.warning: + return theme.colors.orange; + case WidgetSeverity.negative: + return theme.colors.red; + case WidgetSeverity.neutral: + return theme.colors.borderDisabled; + case WidgetSeverity.custom: + return customColor ?? theme.colors.surfaceDisabled; + } + } + + Color _badgeForegroundColor(Zeta theme) { + switch (severity) { + case WidgetSeverity.info: + return theme.colors.textDefault; + case WidgetSeverity.positive: + return theme.colors.black; + case WidgetSeverity.warning: + return theme.colors.textInverse; + case WidgetSeverity.negative: + return theme.colors.textDefault; + case WidgetSeverity.neutral: + return theme.colors.white; + case WidgetSeverity.custom: + return theme.colors.white; + } + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('borderType', borderType)) + ..add(EnumProperty('severity', severity)) + ..add(StringProperty('label', label)) + ..add(DiagnosticsProperty('badgeSize', badgeSize)) + ..add(ColorProperty('customColor', customColor)); + } +} diff --git a/lib/src/components/status_label.dart b/lib/src/components/status_label.dart index 303c7c9c..daca41ed 100644 --- a/lib/src/components/status_label.dart +++ b/lib/src/components/status_label.dart @@ -18,33 +18,12 @@ class ZetaStatusLabelColors { final Color accentColor; } -/// Status Label Type -enum ZetaStatusLabelType { - ///Grey Label - neutral, - - ///Purple Label - info, - - ///Green Label - positive, - - ///Yellow Label - warning, - - ///Red Label - negative, - - ///Custom Label - custom -} - ///Zeta Status Label class ZetaStatusLabel extends StatelessWidget { ///Constructs [ZetaStatusLabel]. const ZetaStatusLabel({ required this.label, - this.labelType = ZetaStatusLabelType.neutral, + this.severity = WidgetSeverity.neutral, this.isDefaultIcon = true, this.customIcon, this.borderType = BorderType.sharp, @@ -68,10 +47,10 @@ class ZetaStatusLabel extends StatelessWidget { ///Size of the label final Size labelSize; - ///The type of the label + ///Widget Severity /// /// Defaults to "neutral" - final ZetaStatusLabelType labelType; + final WidgetSeverity severity; ///Label final String label; @@ -146,30 +125,30 @@ class ZetaStatusLabel extends StatelessWidget { backgroundColor: theme.colors.surfaceDisabled, accentColor: theme.colors.borderDefault, ); - switch (labelType) { - case ZetaStatusLabelType.neutral: + switch (severity) { + case WidgetSeverity.neutral: return defaultColorScheme; - case ZetaStatusLabelType.info: + case WidgetSeverity.info: return ZetaStatusLabelColors( backgroundColor: theme.colors.purple.shade10, accentColor: theme.colors.purple.shade50, ); - case ZetaStatusLabelType.positive: + case WidgetSeverity.positive: return ZetaStatusLabelColors( backgroundColor: theme.colors.green.shade10, accentColor: theme.colors.green.shade50, ); - case ZetaStatusLabelType.warning: + case WidgetSeverity.warning: return ZetaStatusLabelColors( backgroundColor: theme.colors.orange.shade10, accentColor: theme.colors.orange.shade50, ); - case ZetaStatusLabelType.negative: + case WidgetSeverity.negative: return ZetaStatusLabelColors( backgroundColor: theme.colors.red.shade10, accentColor: theme.colors.red.shade50, ); - case ZetaStatusLabelType.custom: + case WidgetSeverity.custom: return customColors ?? defaultColorScheme; } } @@ -181,7 +160,7 @@ class ZetaStatusLabel extends StatelessWidget { ..add(EnumProperty('borderType', borderType)) ..add(DoubleProperty('borderWidth', borderWidth)) ..add(DiagnosticsProperty('labelSize', labelSize)) - ..add(EnumProperty('labelType', labelType)) + ..add(EnumProperty('severity', severity)) ..add(StringProperty('label', label)) ..add( DiagnosticsProperty( diff --git a/lib/src/utils/enums.dart b/lib/src/utils/enums.dart index 5a98cae7..9760794b 100644 --- a/lib/src/utils/enums.dart +++ b/lib/src/utils/enums.dart @@ -6,3 +6,24 @@ enum BorderType { ///rounded border rounded, } + +/// Widget Severity +enum WidgetSeverity { + ///Grey Label + neutral, + + ///Purple Label + info, + + ///Green Label + positive, + + ///Yellow Label + warning, + + ///Red Label + negative, + + ///Custom Label + custom +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index f7c9d73d..793070b8 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -1,6 +1,7 @@ /// Zebra Design System (Zeta) - Flutter Component Library library zeta_flutter; +export 'src/components/badge.dart'; export 'src/components/grid.dart'; export 'src/components/indicator.dart'; export 'src/components/priority_pill.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 69852d48..ef39354a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.0+7 +version: 0.1.0+8 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. From 063386f83490bf3bfb6d26fc6a95dd445006d656 Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Tue, 12 Dec 2023 19:23:36 +0200 Subject: [PATCH 10/41] some sizings were not exactly as shown in Figma (#33) * . * [automated commit] lint format and import sort --------- Co-authored-by: github-actions --- CHANGELOG.md | 103 ++++++++++++++++++-------- example/pubspec.lock | 2 +- lib/src/components/priority_pill.dart | 10 +-- lib/src/components/status_label.dart | 10 +-- pubspec.yaml | 2 +- 5 files changed, 86 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24e03fa1..60a1217b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,47 @@ +## [0.1.0+9] - 2023-12-12 +### :flying_saucer: Other Changes +- [`b97fd3b`](https://github.com/zebratechnologies/zeta-flutter/commit/b97fd3bd881a85c8d4ee4f5ea5856e7a8ebf2d09) - Badge ([#29](https://github.com/zebratechnologies/zeta-flutter/pull/29)) + +* initial + +* Badge + +* fix test + +* [automated commit] lint format and import sort + +* change default border type + +* fix test + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* fix example + +* fix sizing + +* add foreground colors + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`30fd121`](https://github.com/zebratechnologies/zeta-flutter/commit/30fd12131af2549c0b5b31bf89e12553557a009b) - some sizings were not exactly as shown in Figma ([#33](https://github.com/zebratechnologies/zeta-flutter/pull/33)) + +* . + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + ## [0.1.0+8] - 2023-12-11 ### :flying_saucer: Other Changes - [`36f72c1`](https://github.com/zebratechnologies/zeta-flutter/commit/36f72c1df09fecc9d3eeb6dbf1bbf889493529c0) - Component indicator ([#30](https://github.com/zebratechnologies/zeta-flutter/pull/30)) @@ -22,34 +66,34 @@ Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - [`895bbfa`](https://github.com/zebratechnologies/zeta-flutter/commit/895bbfa876c7fea331d6bdb14c77e25632aab28d) - Badge ([#29](https://github.com/zebratechnologies/zeta-flutter/pull/29)) -* initial - -* Badge - -* fix test - -* [automated commit] lint format and import sort - -* change default border type - -* fix test - -* [automated commit] lint format and import sort - -* [automated commit] lint format and import sort - -* [automated commit] lint format and import sort - -* fix example - -* fix sizing - -* add foreground colors - -* [automated commit] lint format and import sort - ---------- - +* initial + +* Badge + +* fix test + +* [automated commit] lint format and import sort + +* change default border type + +* fix test + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* fix example + +* fix sizing + +* add foreground colors + +* [automated commit] lint format and import sort + +--------- + Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* @@ -433,4 +477,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.0+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+4...0.1.0+5 [0.1.0+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+5...0.1.0+6 [0.1.0+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+6...0.1.0+7 -[0.1.0+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+7...0.1.0+8 \ No newline at end of file +[0.1.0+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+7...0.1.0+8 +[0.1.0+9]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+8...0.1.0+9 \ No newline at end of file diff --git a/example/pubspec.lock b/example/pubspec.lock index 0f9ebfcd..7310c025 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -379,7 +379,7 @@ packages: path: ".." relative: true source: path - version: "0.1.0+7" + version: "0.1.0+8" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/lib/src/components/priority_pill.dart b/lib/src/components/priority_pill.dart index a39f8ea2..d90754bb 100644 --- a/lib/src/components/priority_pill.dart +++ b/lib/src/components/priority_pill.dart @@ -52,15 +52,15 @@ class ZetaPriorityPill extends StatelessWidget { Widget _buildIndexContainer(Zeta theme) { return Container( alignment: Alignment.center, - height: Dimensions.l, - width: Dimensions.l, + height: Dimensions.x7, + width: _isBorderRounded ? Dimensions.x7 : Dimensions.x6, decoration: BoxDecoration( shape: _isBorderRounded ? BoxShape.circle : BoxShape.rectangle, color: theme.colors.blue.shade60, ), child: Text( '$index', - style: ZetaText.zetaBodyMedium.apply(color: theme.colors.white), + style: ZetaText.zetaTitleSmall.apply(color: theme.colors.white), ), ); } @@ -68,10 +68,10 @@ class ZetaPriorityPill extends StatelessWidget { Widget _buildPriorityText() { return Flexible( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: Dimensions.s), + padding: const EdgeInsets.fromLTRB(8, 4, 8, 4), child: Text( priority, - style: ZetaText.zetaBodyMedium, + style: ZetaText.zetaTitleSmall, overflow: TextOverflow.ellipsis, ), ), diff --git a/lib/src/components/status_label.dart b/lib/src/components/status_label.dart index daca41ed..5b80b823 100644 --- a/lib/src/components/status_label.dart +++ b/lib/src/components/status_label.dart @@ -27,7 +27,7 @@ class ZetaStatusLabel extends StatelessWidget { this.isDefaultIcon = true, this.customIcon, this.borderType = BorderType.sharp, - this.labelSize = const Size(80, 25), + this.labelSize = const Size(67, 24), this.borderWidth = 1, this.customColors, this.customIconSize = 20.0, @@ -87,13 +87,13 @@ class ZetaStatusLabel extends StatelessWidget { return BoxDecoration( color: colors.backgroundColor, border: Border.all(color: colors.accentColor, width: borderWidth), - borderRadius: BorderRadius.circular(borderType == BorderType.rounded ? 15.0 : 0.0), + borderRadius: BorderRadius.circular(borderType == BorderType.rounded ? 10.0 : 0.0), ); } Widget _buildContent(ZetaStatusLabelColors colors, Zeta theme) { return Padding( - padding: const EdgeInsets.symmetric(horizontal: Dimensions.xxs), + padding: const EdgeInsets.fromLTRB(8, 2, 8, 2), child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -102,7 +102,7 @@ class ZetaStatusLabel extends StatelessWidget { Flexible( child: Text( label, - style: ZetaText.zetaTitleMedium, + style: ZetaText.zetaTitleSmall, overflow: TextOverflow.ellipsis, ), ), @@ -112,7 +112,7 @@ class ZetaStatusLabel extends StatelessWidget { } Icon _buildIcon(ZetaStatusLabelColors colors) { - final size = isDefaultIcon ? 12.0 : customIconSize; + final size = isDefaultIcon ? Dimensions.x2 : customIconSize; return Icon( size: size, isDefaultIcon ? Icons.circle : (customIcon ?? Icons.star), diff --git a/pubspec.yaml b/pubspec.yaml index ef39354a..5d8f8d99 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.0+8 +version: 0.1.0+9 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. From 5f0a33e8e3b92de83d83170f267e6cd3f5fca068 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Wed, 13 Dec 2023 17:16:38 +0000 Subject: [PATCH 11/41] Merge from zebradevs (#27) * Merge from zebradevs * spelling and finals * [automated commit] lint format and import sort --------- Co-authored-by: github-actions --- CHANGELOG.md | 184 ++++++--- all_lint_rules.yaml | 223 ---------- android/.gitignore | 9 - .../plugins/GeneratedPluginRegistrant.java | 23 -- android/build.gradle | 46 --- android/settings.gradle | 1 - android/src/main/AndroidManifest.xml | 3 - docs/components/Grid/flutter.md | 59 --- docs/components/Spacing/flutter.md | 198 --------- docs/components/Typography/flutter.md | 98 ----- docs/flutter.template.md | 66 --- example/lib/home.dart | 2 + example/lib/main.dart | 36 +- example/lib/pages/badge_example.dart | 1 - example/lib/pages/checkbox_example.dart | 77 ++++ example/lib/pages/priority_pill_example.dart | 1 - example/lib/pages/status_label_example.dart | 1 - example/lib/pages/theme_color_switch.dart | 50 +-- example/lib/pages/theme_constrast_switch.dart | 2 +- example/lib/pages/theme_mode_switch.dart | 2 +- example/lib/theme_service.dart | 47 +++ example/lib/widgets.dart | 4 +- .../Flutter/GeneratedPluginRegistrant.swift | 2 + example/macos/Podfile.lock | 7 + example/pubspec.lock | 385 ------------------ example/pubspec.yaml | 3 +- example/test/badge_test.dart | 1 - example/test/checkbox_test.dart | 72 ++++ .../components/badge_widgetbook.dart | 1 - .../components/checkbox_widgetbook.dart | 38 ++ .../components/priority_pill_widgetbook.dart | 1 - .../components/status_label_widgetbook.dart | 1 - example/widgetbook/widgetbook.dart | 4 +- ios/.gitignore | 38 -- ios/Assets/.gitkeep | 0 ios/Classes/ZetaFlutterPlugin.swift | 14 - ios/Classes/ZetaPlugin.swift | 14 - ios/zeta.podspec | 23 -- ios/zeta_flutter.podspec | 23 -- lib/src/components/badge.dart | 1 - lib/src/components/checkbox.dart | 192 +++++++++ lib/src/components/priority_pill.dart | 1 - lib/src/components/status_label.dart | 1 - lib/src/theme/colors.dart | 4 +- lib/src/theme/theme_service.dart | 26 +- lib/src/zeta.dart | 25 +- lib/zeta_flutter.dart | 3 + pubspec.yaml | 2 +- 48 files changed, 663 insertions(+), 1352 deletions(-) delete mode 100644 all_lint_rules.yaml delete mode 100644 android/.gitignore delete mode 100644 android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java delete mode 100644 android/build.gradle delete mode 100644 android/settings.gradle delete mode 100644 android/src/main/AndroidManifest.xml delete mode 100644 docs/components/Grid/flutter.md delete mode 100644 docs/components/Spacing/flutter.md delete mode 100644 docs/components/Typography/flutter.md delete mode 100644 docs/flutter.template.md create mode 100644 example/lib/pages/checkbox_example.dart create mode 100644 example/lib/theme_service.dart delete mode 100644 example/pubspec.lock create mode 100644 example/test/checkbox_test.dart create mode 100644 example/widgetbook/components/checkbox_widgetbook.dart delete mode 100644 ios/.gitignore delete mode 100644 ios/Assets/.gitkeep delete mode 100644 ios/Classes/ZetaFlutterPlugin.swift delete mode 100644 ios/Classes/ZetaPlugin.swift delete mode 100644 ios/zeta.podspec delete mode 100644 ios/zeta_flutter.podspec create mode 100644 lib/src/components/checkbox.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 60a1217b..41d0a4f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ +## [0.1.1+2] - 2023-12-13 +### :flying_saucer: Other Changes +- [`063386f`](https://github.com/zebratechnologies/zeta-flutter/commit/063386f83490bf3bfb6d26fc6a95dd445006d656) - some sizings were not exactly as shown in Figma ([#33](https://github.com/zebratechnologies/zeta-flutter/pull/33)) + +* . + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`1c8ca4c`](https://github.com/zebratechnologies/zeta-flutter/commit/1c8ca4c4b5dbd8378710a18765303a6d37472cf0) - Merge from zebradevs ([#27](https://github.com/zebratechnologies/zeta-flutter/pull/27)) + +* Merge from zebradevs + +* spelling and finals + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@thelukewalton](https://github.com/thelukewalton))* + + +## [0.1.1+1] - 2023-12-01 + +- feature: Refactor theme declaration and introduce theme service + +Theme extensions were deleted and its contents were moved to colors.dart to consolidate all color-related codes in one file for easier navigation and editing. Additional enhancements include optimizing color assignments and making ZetaColors immutable for more robust color management. + ## [0.1.0+9] - 2023-12-12 + ### :flying_saucer: Other Changes + - [`b97fd3b`](https://github.com/zebratechnologies/zeta-flutter/commit/b97fd3bd881a85c8d4ee4f5ea5856e7a8ebf2d09) - Badge ([#29](https://github.com/zebratechnologies/zeta-flutter/pull/29)) * initial @@ -28,22 +60,24 @@ * [automated commit] lint format and import sort ---------- +--- + +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`30fd121`](https://github.com/zebratechnologies/zeta-flutter/commit/30fd12131af2549c0b5b31bf89e12553557a009b) - some sizings were not exactly as shown in Figma ([#33](https://github.com/zebratechnologies/zeta-flutter/pull/33)) -* . - -* [automated commit] lint format and import sort - ---------- - -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +* . +* [automated commit] lint format and import sort + +--- + +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.0+8] - 2023-12-11 + ### :flying_saucer: Other Changes + - [`36f72c1`](https://github.com/zebratechnologies/zeta-flutter/commit/36f72c1df09fecc9d3eeb6dbf1bbf889493529c0) - Component indicator ([#30](https://github.com/zebratechnologies/zeta-flutter/pull/30)) * add icons @@ -60,10 +94,11 @@ Co-authored-by: github-actions *(commit by [@genovev * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ + - [`895bbfa`](https://github.com/zebratechnologies/zeta-flutter/commit/895bbfa876c7fea331d6bdb14c77e25632aab28d) - Badge ([#29](https://github.com/zebratechnologies/zeta-flutter/pull/29)) * initial @@ -92,13 +127,14 @@ Co-authored-by: github-actions *(commit by [@atanasy * [automated commit] lint format and import sort ---------- - -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +--- +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.0+7] - 2023-12-11 + ### :flying_saucer: Other Changes + - [`19e7d93`](https://github.com/zebratechnologies/zeta-flutter/commit/19e7d933456938d473f1f5c6ef2696e02349e196) - Priority Pill ([#28](https://github.com/zebratechnologies/zeta-flutter/pull/28)) * Priority Pill @@ -109,9 +145,10 @@ Co-authored-by: github-actions *(commit by [@genovev * [automated commit] lint format and import sort ---------- +--- + +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`fe4fe8d`](https://github.com/zebratechnologies/zeta-flutter/commit/fe4fe8d088fddf9443ce5810a1d2c068b13c75d9) - Component indicator ([#30](https://github.com/zebratechnologies/zeta-flutter/pull/30)) * add icons @@ -128,14 +165,15 @@ Co-authored-by: github-actions *(commit by [@genovev * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.0+6] - 2023-12-08 + ### :flying_saucer: Other Changes + - [`2f21a18`](https://github.com/zebratechnologies/zeta-flutter/commit/2f21a18e30425fe91fe7bb0ee3c4df7ab8baca35) - add icons ([#24](https://github.com/zebratechnologies/zeta-flutter/pull/24)) * add icons @@ -144,10 +182,11 @@ Co-authored-by: github-actions *(commit by [@atanasy * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ + - [`2442420`](https://github.com/zebratechnologies/zeta-flutter/commit/2442420da15739e538d50e14c2a18c63de8d6f96) - Priority Pill ([#28](https://github.com/zebratechnologies/zeta-flutter/pull/28)) * Priority Pill @@ -158,13 +197,14 @@ Co-authored-by: github-actions *(commit by [@atanasy * [automated commit] lint format and import sort ---------- - -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +--- +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.0+5] - 2023-12-08 + ### :flying_saucer: Other Changes + - [`ef44d24`](https://github.com/zebratechnologies/zeta-flutter/commit/ef44d244589a7cc652a934f25a5122bbd1657c05) - status_label ([#25](https://github.com/zebratechnologies/zeta-flutter/pull/25)) * status_label @@ -178,26 +218,30 @@ Co-authored-by: github-actions *(commit by [@genovev * chore(deps): bump tj-actions/branch-names in /.github/workflows ([#26](https://github.com/zebratechnologies/zeta-flutter/pull/26)) Bumps [tj-actions/branch-names](https://github.com/tj-actions/branch-names) from 5.1 to 7.0.7. + - [Release notes](https://github.com/tj-actions/branch-names/releases) - [Changelog](https://github.com/tj-actions/branch-names/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/branch-names/compare/v5.1...v7.0.7) --- + updated-dependencies: + - dependency-name: tj-actions/branch-names dependency-type: direct:production -... + ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> -* [automated commit] lint format and import sort +- [automated commit] lint format and import sort ---------- +--- Signed-off-by: dependabot[bot] Co-authored-by: github-actions -Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ + - [`c90349b`](https://github.com/zebratechnologies/zeta-flutter/commit/c90349b104f3000956f821934b01dfd74f37a5e2) - add icons ([#24](https://github.com/zebratechnologies/zeta-flutter/pull/24)) * add icons @@ -206,17 +250,19 @@ Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.c * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.0+4] - 2023-12-06 + ### :wrench: Chores -- [`0794b08`](https://github.com/zebratechnologies/zeta-flutter/commit/0794b08d029e9954457dbfac56bd576aaf8f0e82) - **deps**: bump tj-actions/branch-names in /.github/workflows *(PR [#26](https://github.com/zebratechnologies/zeta-flutter/pull/26) by [@dependabot[bot]](https://github.com/apps/dependabot))* + +- [`0794b08`](https://github.com/zebratechnologies/zeta-flutter/commit/0794b08d029e9954457dbfac56bd576aaf8f0e82) - **deps**: bump tj-actions/branch-names in /.github/workflows _(PR [#26](https://github.com/zebratechnologies/zeta-flutter/pull/26) by [@dependabot[bot]](https://github.com/apps/dependabot))_ ### :flying_saucer: Other Changes + - [`65bf57f`](https://github.com/zebratechnologies/zeta-flutter/commit/65bf57fc1d7f13d4017b0e21f5f52d62552b502c) - status_label ([#25](https://github.com/zebratechnologies/zeta-flutter/pull/25)) * status_label @@ -230,33 +276,38 @@ Co-authored-by: github-actions *(commit by [@atanasy * chore(deps): bump tj-actions/branch-names in /.github/workflows ([#26](https://github.com/zebratechnologies/zeta-flutter/pull/26)) Bumps [tj-actions/branch-names](https://github.com/tj-actions/branch-names) from 5.1 to 7.0.7. + - [Release notes](https://github.com/tj-actions/branch-names/releases) - [Changelog](https://github.com/tj-actions/branch-names/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/branch-names/compare/v5.1...v7.0.7) --- + updated-dependencies: + - dependency-name: tj-actions/branch-names dependency-type: direct:production -... + ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> -* [automated commit] lint format and import sort +- [automated commit] lint format and import sort ---------- +--- Signed-off-by: dependabot[bot] Co-authored-by: github-actions -Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.0+3] - 2023-12-06 + ### :wrench: Chores -- [`63b94a6`](https://github.com/zebratechnologies/zeta-flutter/commit/63b94a60da570ce3848aa9c1af7a129a2c952399) - **deps**: bump tj-actions/branch-names in /.github/workflows *(PR [#26](https://github.com/zebratechnologies/zeta-flutter/pull/26) by [@dependabot[bot]](https://github.com/apps/dependabot))* + +- [`63b94a6`](https://github.com/zebratechnologies/zeta-flutter/commit/63b94a60da570ce3848aa9c1af7a129a2c952399) - **deps**: bump tj-actions/branch-names in /.github/workflows _(PR [#26](https://github.com/zebratechnologies/zeta-flutter/pull/26) by [@dependabot[bot]](https://github.com/apps/dependabot))_ ### :flying_saucer: Other Changes + - [`f333429`](https://github.com/zebratechnologies/zeta-flutter/commit/f333429083f0cf790627211788e69285bcff3a37) - Cleanup dart warnings; fix text scale ([#23](https://github.com/zebratechnologies/zeta-flutter/pull/23)) * fix endtemplate in comments; upgrade flutter packages @@ -265,31 +316,45 @@ Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.c * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.0+2] - 2023-12-01 + ### :wrench: Chores -- [`d22dd29`](https://github.com/zebratechnologies/zeta-flutter/commit/d22dd29b506affccc8cdc7ecfb15a57fcf330646) - Tidy, reorganise and prepare repo *(commit by [@thelukewalton](https://github.com/thelukewalton))* + +- [`d22dd29`](https://github.com/zebratechnologies/zeta-flutter/commit/d22dd29b506affccc8cdc7ecfb15a57fcf330646) - Tidy, reorganise and prepare repo _(commit by [@thelukewalton](https://github.com/thelukewalton))_ ### :flying_saucer: Other Changes -- [`199328c`](https://github.com/zebratechnologies/zeta-flutter/commit/199328c28ccfa8a05a1494c08ad93aaf13dd3b28) - Update to mirror 0.1.0+1 from ZebraDevs *(commit by [@thelukewalton](https://github.com/thelukewalton))* + +- [`199328c`](https://github.com/zebratechnologies/zeta-flutter/commit/199328c28ccfa8a05a1494c08ad93aaf13dd3b28) - Update to mirror 0.1.0+1 from ZebraDevs _(commit by [@thelukewalton](https://github.com/thelukewalton))_ - [`0ee6171`](https://github.com/zebratechnologies/zeta-flutter/commit/0ee6171e779c6db9995308aa35f2f598b9db372c) - Cleanup dart warnings; fix text scale ([#23](https://github.com/zebratechnologies/zeta-flutter/pull/23)) * fix endtemplate in comments; upgrade flutter packages + <<<<<<< HEAD * remove unnecessary text scaling * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ +======= + +> > > > > > > 38a5a89 (Merge from zebradevs) +- remove unnecessary text scaling + +- [automated commit] lint format and import sort + +--- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.0+1] - 2023-11-28 @@ -384,15 +449,15 @@ Introduced license details for third-party libraries used in the project. MIT li * bug(type): Fixing reset height and tests failing _(commit by [@thelukewalton](https://github.com/thelukewalton))_ -## 0.0.1+11 - 2023-08-09 +## [0.0.1+11] - 2023-08-09 ### :sparkles: New Features - [`193dc42`](https://github.com/zebratechnologies/zeta-flutter/commit/193dc42c8e7419d9087afdffce0eae915af12819) - Color ([#21](https://github.com/zebratechnologies/zeta-flutter/pull/21)) _(commit by [@thelukewalton](https://github.com/thelukewalton))_ - - [`a605819`](https://github.com/zebratechnologies/zeta-flutter/commit/a60581973764b5d06711fe6470f9963af934b7ad) - Adding color defs by [@thelukewalton](https://github.com/thelukewalton) - - [`f519cd8`](https://github.com/zebratechnologies/zeta-flutter/commit/f519cd856c7b4793ea7e24dc16f3abba0cffcf66) - starting colorswatch util by [@thelukewalton](https://github.com/thelukewalton) - - [`7445db0`](https://github.com/zebratechnologies/zeta-flutter/commit/7445db0b7da2434f5a55d3067369b3bd35df363b) - adding widgetbook and tests by [@thelukewalton](https://github.com/thelukewalton) +- [`a605819`](https://github.com/zebratechnologies/zeta-flutter/commit/a60581973764b5d06711fe6470f9963af934b7ad) - Adding color defs by [@thelukewalton](https://github.com/thelukewalton) +- [`f519cd8`](https://github.com/zebratechnologies/zeta-flutter/commit/f519cd856c7b4793ea7e24dc16f3abba0cffcf66) - starting colorswatch util by [@thelukewalton](https://github.com/thelukewalton) +- [`7445db0`](https://github.com/zebratechnologies/zeta-flutter/commit/7445db0b7da2434f5a55d3067369b3bd35df363b) - adding widgetbook and tests by [@thelukewalton](https://github.com/thelukewalton) ### :bug: Bug Fixes @@ -400,7 +465,7 @@ Introduced license details for third-party libraries used in the project. MIT li - [`3479adb`](https://github.com/zebratechnologies/zeta-flutter/commit/3479adb574c9ec1073552f888631f7cee12fe4cb) -bug(platforms): adding windows into example by [@thelukewalton](https://github.com/thelukewalton) - [`70a6144`](https://github.com/zebratechnologies/zeta-flutter/commit/70a614446c4d526315eb3229478d89dbd1c031de) - bug(type): Fixing reset height and tests failing by [@thelukewalton](https://github.com/thelukewalton) -## 0.0.1+10 - 2023-07-11 +## [0.0.1+10] - 2023-07-11 ### :sparkles: New Features @@ -413,7 +478,7 @@ Introduced license details for third-party libraries used in the project. MIT li - [`988964e`](https://github.com/zebratechnologies/zeta-flutter/commit/988964e122128c4f9e4423fd849b70b6283ccea7) - removing unused dependency; by [@thelukewalton](https://github.com/thelukewalton) -## 0.0.1+9 - 2023-03-28 +## [0.0.1+9]- 2023-03-28 ### :sparkles: New Features @@ -433,7 +498,7 @@ Introduced license details for third-party libraries used in the project. MIT li - [`d591856`](https://github.com/zebratechnologies/zeta-flutter/commit/d59185680879bf2f938c4f2a6bd2328f29a3ddd2) - test _(commit by [@thelukewalton](https://github.com/thelukewalton))_ - [`1dcbcae`](https://github.com/zebratechnologies/zeta-flutter/commit/1dcbcaec2600210efcefc80861c29aaa7e44c27e) - removing hardcoded shas _(PR [#19](https://github.com/zebratechnologies/zeta-flutter/pull/19) by [@thelukewalton](https://github.com/thelukewalton))_ -## 0.0.1+6 - Spacing - 2023-03-06 +## [0.0.1+6]- Spacing - 2023-03-06 ### :sparkles: New Features @@ -448,7 +513,7 @@ Introduced license details for third-party libraries used in the project. MIT li - [`1dc0e1b`](https://github.com/zebratechnologies/zeta-flutter/commit/1dc0e1b64cb870685110516c5159b20fb903f2c3) - Update README.md _(commit by [@benken](https://github.com/benken))_ -## 0.0.1+5 - Grid - 2023-02-17 +## [0.0.1+5] - Grid - 2023-02-17 ### :sparkles: New Features @@ -465,17 +530,8 @@ Introduced license details for third-party libraries used in the project. MIT li - [`4acf3c1`](https://github.com/zebratechnologies/zeta-flutter/commit/4acf3c1134b6c8d17827d8e2c665250d6f6ead1d) - fix(actions) Fix action refs _(PR [#7](https://github.com/zebratechnologies/zeta-flutter/pull/7) by [@thelukewalton](https://github.com/thelukewalton))_ - [`83e073b`](https://github.com/zebratechnologies/zeta-flutter/commit/83e073b16808d89373a74dba35172bb7a978e765) - fix(actions) another attempt at fixing actions checkout _(PR [#8](https://github.com/zebratechnologies/zeta-flutter/pull/8) by [@thelukewalton](https://github.com/thelukewalton))_ -## 0.0.1+1 - Initial setup +## [0.0.1+1] - Initial setup - Initial setup -[0.0.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+11...0.0.1+12 - -[0.1.0+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.0.1+12...0.1.0+2 -[0.1.0+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+2...0.1.0+3 -[0.1.0+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+3...0.1.0+4 -[0.1.0+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+4...0.1.0+5 -[0.1.0+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+5...0.1.0+6 -[0.1.0+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+6...0.1.0+7 -[0.1.0+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+7...0.1.0+8 -[0.1.0+9]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+8...0.1.0+9 \ No newline at end of file +[0.1.1+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+9...0.1.1+2 \ No newline at end of file diff --git a/all_lint_rules.yaml b/all_lint_rules.yaml deleted file mode 100644 index bf6b1ae4..00000000 --- a/all_lint_rules.yaml +++ /dev/null @@ -1,223 +0,0 @@ -linter: - rules: - - always_use_package_imports - - avoid_dynamic_calls - - avoid_empty_else - - avoid_print - - avoid_relative_lib_imports - - avoid_returning_null_for_future - - avoid_slow_async_io - - avoid_type_to_string - - avoid_types_as_parameter_names - - avoid_web_libraries_in_flutter - - cancel_subscriptions - - close_sinks - - collection_methods_unrelated_type - - comment_references - - control_flow_in_finally - - deprecated_member_use_from_same_package - - diagnostic_describe_all_properties - - discarded_futures - - empty_statements - - hash_and_equals - - implicit_reopen - - invalid_case_patterns - - iterable_contains_unrelated_type - - list_remove_unrelated_type - - literal_only_boolean_expressions - - no_adjacent_strings_in_list - - no_duplicate_case_values - - no_logic_in_create_state - - no_self_assignments - - no_wildcard_variable_uses - - prefer_relative_imports - - prefer_void_to_null - - test_types_in_equals - - throw_in_finally - - unnecessary_statements - - unrelated_type_equality_checks - - unsafe_html - - use_build_context_synchronously - - use_key_in_widget_constructors - - valid_regexps - - depend_on_referenced_packages - - package_names - - secure_pubspec_urls - - sort_pub_dependencies - - always_declare_return_types - - always_put_control_body_on_new_line - - always_put_required_named_parameters_first - - always_require_non_null_named_parameters - - always_specify_types - - annotate_overrides - - avoid_annotating_with_dynamic - - avoid_bool_literals_in_conditional_expressions - - avoid_catches_without_on_clauses - - avoid_catching_errors - - avoid_classes_with_only_static_members - - avoid_double_and_int_checks - - avoid_equals_and_hash_code_on_mutable_classes - - avoid_escaping_inner_quotes - - avoid_field_initializers_in_const_classes - - avoid_final_parameters - - avoid_function_literals_in_foreach_calls - - avoid_implementing_value_types - - avoid_init_to_null - - avoid_js_rounded_ints - - avoid_multiple_declarations_per_line - - avoid_null_checks_in_equality_operators - - avoid_positional_boolean_parameters - - avoid_private_typedef_functions - - avoid_redundant_argument_values - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - - avoid_returning_null - - avoid_returning_null_for_void - - avoid_returning_this - - avoid_setters_without_getters - - avoid_shadowing_type_parameters - - avoid_single_cascade_in_expression_statements - - avoid_types_on_closure_parameters - - avoid_unnecessary_containers - - avoid_unused_constructor_parameters - - avoid_void_async - - await_only_futures - - camel_case_extensions - - camel_case_types - - cascade_invocations - - cast_nullable_to_non_nullable - - combinators_ordering - - conditional_uri_does_not_exist - - constant_identifier_names - - curly_braces_in_flow_control_structures - - dangling_library_doc_comments - - deprecated_consistency - - directives_ordering - - do_not_use_environment - - empty_catches - - empty_constructor_bodies - - eol_at_end_of_file - - exhaustive_cases - - file_names - - flutter_style_todos - - implementation_imports - - implicit_call_tearoffs - - join_return_with_assignment - - leading_newlines_in_multiline_strings - - library_annotations - - library_names - - library_prefixes - - library_private_types_in_public_api - - lines_longer_than_80_chars - - matching_super_parameters - - missing_whitespace_between_adjacent_strings - - no_default_cases - - no_leading_underscores_for_library_prefixes - - no_leading_underscores_for_local_identifiers - - no_literal_bool_comparisons - - no_runtimeType_toString - - non_constant_identifier_names - - noop_primitive_operations - - null_check_on_nullable_type_parameter - - null_closures - - omit_local_variable_types - - one_member_abstracts - - only_throw_errors - - overridden_fields - - package_api_docs - - package_prefixed_library_names - - parameter_assignments - - prefer_adjacent_string_concatenation - - prefer_asserts_in_initializer_lists - - prefer_asserts_with_message - - prefer_collection_literals - - prefer_conditional_assignment - - prefer_const_constructors - - prefer_const_constructors_in_immutables - - prefer_const_declarations - - prefer_const_literals_to_create_immutables - - prefer_constructors_over_static_methods - - prefer_contains - - prefer_double_quotes - - prefer_expression_function_bodies - - prefer_final_fields - - prefer_final_in_for_each - - prefer_final_locals - - prefer_final_parameters - - prefer_for_elements_to_map_fromIterable - - prefer_foreach - - prefer_function_declarations_over_variables - - prefer_generic_function_type_aliases - - prefer_if_elements_to_conditional_expressions - - prefer_if_null_operators - - prefer_initializing_formals - - prefer_inlined_adds - - prefer_int_literals - - prefer_interpolation_to_compose_strings - - prefer_is_empty - - prefer_is_not_empty - - prefer_is_not_operator - - prefer_iterable_whereType - - prefer_mixin - - prefer_null_aware_method_calls - - prefer_null_aware_operators - - prefer_single_quotes - - prefer_spread_collections - - prefer_typing_uninitialized_variables - - provide_deprecation_message - - public_member_api_docs - - recursive_getters - - require_trailing_commas - - sized_box_for_whitespace - - sized_box_shrink_expand - - slash_for_doc_comments - - sort_child_properties_last - - sort_constructors_first - - sort_unnamed_constructors_first - - tighten_type_of_initializing_formals - - type_annotate_public_apis - - type_init_formals - - type_literal_in_constant_pattern - - unawaited_futures - - unnecessary_await_in_return - - unnecessary_brace_in_string_interps - - unnecessary_breaks - - unnecessary_const - - unnecessary_constructor_name - - unnecessary_final - - unnecessary_getters_setters - - unnecessary_lambdas - - unnecessary_late - - unnecessary_library_directive - - unnecessary_new - - unnecessary_null_aware_assignments - - unnecessary_null_aware_operator_on_extension_on_nullable - - unnecessary_null_checks - - unnecessary_null_in_if_null_operators - - unnecessary_nullable_for_final_variable_declarations - - unnecessary_overrides - - unnecessary_parenthesis - - unnecessary_raw_strings - - unnecessary_string_escapes - - unnecessary_string_interpolations - - unnecessary_this - - unnecessary_to_list_in_spreads - - unreachable_from_main - - use_colored_box - - use_decorated_box - - use_enums - - use_full_hex_values_for_flutter_colors - - use_function_type_syntax_for_parameters - - use_if_null_to_convert_nulls_to_bools - - use_is_even_rather_than_modulo - - use_late_for_private_fields_and_variables - - use_named_constants - - use_raw_strings - - use_rethrow_when_possible - - use_setters_to_change_properties - - use_string_buffers - - use_string_in_part_of_directives - - use_super_parameters - - use_test_throws_matchers - - use_to_and_as_if_applicable - - void_checks diff --git a/android/.gitignore b/android/.gitignore deleted file mode 100644 index 161bdcda..00000000 --- a/android/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures -.cxx diff --git a/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java deleted file mode 100644 index d007606a..00000000 --- a/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.flutter.plugins; - -import io.flutter.plugin.common.PluginRegistry; - -/** - * Generated file. Do not edit. - */ -public final class GeneratedPluginRegistrant { - public static void registerWith(PluginRegistry registry) { - if (alreadyRegisteredWith(registry)) { - return; - } - } - - private static boolean alreadyRegisteredWith(PluginRegistry registry) { - final String key = GeneratedPluginRegistrant.class.getCanonicalName(); - if (registry.hasPlugin(key)) { - return true; - } - registry.registrarFor(key); - return false; - } -} diff --git a/android/build.gradle b/android/build.gradle deleted file mode 100644 index 667340b6..00000000 --- a/android/build.gradle +++ /dev/null @@ -1,46 +0,0 @@ -group 'com.zebra.zeta.zeta' -version '1.0-SNAPSHOT' - -buildscript { - ext.kotlin_version = '1.7.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.2.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' - -android { - compileSdkVersion 31 - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - minSdkVersion 16 - } -} diff --git a/android/settings.gradle b/android/settings.gradle deleted file mode 100644 index c60fa759..00000000 --- a/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'zeta' diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml deleted file mode 100644 index ab297369..00000000 --- a/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/docs/components/Grid/flutter.md b/docs/components/Grid/flutter.md deleted file mode 100644 index 0edc52d2..00000000 --- a/docs/components/Grid/flutter.md +++ /dev/null @@ -1,59 +0,0 @@ -## ZetaGrid Usage - -To import ZetaGrid into a Dart file: - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -``` - -### Example - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -class ZetaGridExample extends StatelessWidget{ - const ZetaGridExample({Key? key}) : super(key: key); - @override - Widget build(BuildContext context) { - return ZetaGrid(...); - } -} -``` - -### Setup - -To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: - -```dart -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; -class MyApp extends StatelessWidget { - const MyApp({super.key}); - @override - Widget build(BuildContext context) { - return MaterialApp( - theme: ZetaTheme.zeta, - builder: (context, child) => ..., - ); - } -} -``` - -or - -```dart -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; -class MyApp extends StatelessWidget { - const MyApp({super.key}); - @override - Widget build(BuildContext context) { - return Theme( - data: ZetaTheme.zeta, - child: CupertinoApp( - builder: (context, child) => ..., - ), - ); - } -} -``` diff --git a/docs/components/Spacing/flutter.md b/docs/components/Spacing/flutter.md deleted file mode 100644 index 6eddb8b6..00000000 --- a/docs/components/Spacing/flutter.md +++ /dev/null @@ -1,198 +0,0 @@ -## ZetaSpacing Usage - -To import ZetaSpacing into a Dart file: - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -``` - -### Example - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; - -class ZetaSpacingExample extends StatelessWidget{ - const ZetaSpacingExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ZetaSpacing(...); - } -} -``` - -### Setup - -To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: - -```dart -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - theme: ZetaTheme.zeta, - builder: (context, child) => ..., - ); - } -} -``` - -or - -```dart - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return Theme( - data: ZetaTheme.zeta, - child: CupertinoApp( - builder: (context, child) => ..., - ), - ); - } -} -``` - -### ZetaSpacing - -ZetaSpacing provides four options for spacing - -- `square` - applies inset to all 4 sides equally. -- `squish` - applies inset to top and bottom only. -- `inline` - applies inset to start and end only. -- `inlineStart` - applies inset to start only. For LTR locales this is the left, for RTL locales this is the right. -- `inlineEnd` - applies inset to end only. For LTR locales this is the right, for RTL locales this is the left. -- `stack` - applies inset to bottom only. - -These spacings should be applied with the following doubles: - -- `x0` - 0 -- `x1` - 4 - also `xxs` -- `x2` - 8 - also `xs` -- `x3` - 12 - also `s` -- `x4` - 16 - also `b` -- `x5` - 20 -- `x6` - 24 - also `m` -- `x7` - 28 -- `x8` - 32 - also `l` -- `x9` - 36 -- `x10` - 40 -- `x11` - 44 -- `x12` - 48 -- `x13` - 52 -- `x14` - 58 -- `x16` - 64 - also `xl` -- `x20` - 80 - also `xxl` -- `x24` - 96 - also `xxxl` - -Spacing components can be used in multiple ways: - -### ZetaSpacing() widget with named constructors. - -```dart -const ZetaSpacing.square( - Text('Example'), - size: Dimensions.x1, -), -const ZetaSpacing.squish( - Text('Example'), - size: Dimensions.x1, -), -const ZetaSpacing.stack( - Text('Example'), - size: Dimensions.x1, -) -const ZetaSpacing.inline( - Text('Example'), - size: Dimensions.x1, -) -``` - -This is the preferred way to use ZetaSpacing. Having a const, named constructor makes the intuitive and efficient. - -- Const constructor -- Can wrap any Widget. -- Padding inset around widget. - -
    - -### ZetaSpacing() widget. - -```dart -const ZetaSpacing( - Text('Example'), - size: Dimensions.x1, - type: ZetaSpacingType.square, -), -const ZetaSpacing( - Text('Example'), - size: Dimensions.x1, - type: ZetaSpacingType.squish, -), -const ZetaSpacing( - Text('Example'), - size: Dimensions.x1, - type: ZetaSpacingType.stack, -), -const ZetaSpacing( - Text('Example'), - size: Dimensions.x1, - type: ZetaSpacingType.inline, -), -``` - -This method is less intuitive than using the named constructor, although it does still provide a const constructor for efficiency. - -- Having a const constructor makes this a preferred approach to spacing. -- Can wrap any Widget. -- Padding inset around widget. - -
    - -### SpacingSize extension on double. - -```dart -Container( - padding: Dimensions.x1.square, - margin: Dimensions.x10.squish, - child: Text('Example'), -), -Container( - padding: Dimensions.x1.stack, - margin: Dimensions.x10.inline, - child: Text('Example'), -), -``` - -- Should be used with defined sizes: x0, x1,... or xxs, xs,... (although can be used on any double). -- Can be used for either padding or margin. -- Can be wrapped around any Widget, or used as a parameter. - -
    - -### SpacingWidget extension on Widget. - -```dart -Text('Example').square(Dimensions.x1), -Text('Example').squish(Dimensions.x1), -Text('Example').stack(Dimensions.x1), -Text('Example').inline(Dimensions.x1), -Text('Example').inlineStart(Dimensions.x1), -Text('Example').inlineEnd(Dimensions.x1), -``` - -- Should be used with defined sizes: x0, x1,... or xxs, xs,... (although can be used on any double). -- Padding inset around widget. -- Can be applied to any widget. diff --git a/docs/components/Typography/flutter.md b/docs/components/Typography/flutter.md deleted file mode 100644 index 3bd74554..00000000 --- a/docs/components/Typography/flutter.md +++ /dev/null @@ -1,98 +0,0 @@ -## ZetaText Usage - -To import ZetaText into a Dart file: - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -``` - -### Example - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; - -class ZetaTextExample extends StatelessWidget{ - const ZetaTextExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ZetaText(...); - } -} -``` - -### Setup - -To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: - -```dart -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - theme: ZetaTheme.zeta, - builder: (context, child) => ..., - ); - } -} -``` - -or - -```dart - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return Theme( - data: ZetaTheme.zeta, - child: CupertinoApp( - builder: (context, child) => ..., - ), - ); - } -} -``` - -### ZetaText - -Zeta text styles are within ZetaTheme.zeta, and so will be automatically applied to many widgets that use the built in text theme. When building components, text should not have any spacing by default, and so it is recommended to use the individual text styles with Text, rather than using ZetaText as this will by default apply a x2 squish padding (top and bottom). - -Zeta Typography styles can be used in multiple ways: - -### ZetaText widget with named constructors - -```dart -const ZetaText.bodySmall('Example'), -const ZetaText.displayLarge('Example'), -``` - -This is the preferred way to display text. Having a const, named constructor with helper parameters makes the intuitive and efficient. Constructors exist for all pre-defined text styles and helper functions exist to support all tokens. - -### ZetaText widget - -```dart -const ZetaText('Example', style: ZetaText.zetaBodySmall) -``` - -This method is less intuitive than using the named constructor, although it does still provide a const constructor for efficiency. Having a const, named constructor with helper functions makes the intuitive and efficient. Constructors exist for all pre-defined text styles and helper parameters exist to support all tokens. - -### ZetaText styles - -```dart -Text('Example', style: ZetaText.zetaBodySmall) -Text('Example', style: Theme.of(context).bodySmall) -``` - -Using the base styles gives the greatest flexibility as styles can be extended or added to where needed, at the expense of following the specifications exactly. As ZetaText.textTheme is within the base app style, we can use context to get the styles. This greatly speed up the process of applying Zeta to a pre-existing application. Using this method means helper parameters (such as caps) can not be used and spacing is not applied. This can be useful in components where spacing should be zero. diff --git a/docs/flutter.template.md b/docs/flutter.template.md deleted file mode 100644 index fbbb098f..00000000 --- a/docs/flutter.template.md +++ /dev/null @@ -1,66 +0,0 @@ -## ZetaX Usage - -To import ZetaX into a Dart file: - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -``` - -### Example - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; - -class ZetaXExample extends StatelessWidget{ - const ZetaXExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ZetaY(...); - } -} -``` - -### Setup - -To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: - -```dart -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - theme: ZetaTheme.zeta, - builder: (context, child) => ..., - ); - } -} -``` - -or - -```dart - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return Theme( - data: ZetaTheme.zeta, - child: CupertinoApp( - builder: (context, child) => ..., - ), - ); - } -} -``` diff --git a/example/lib/home.dart b/example/lib/home.dart index ba51d227..93c883ff 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:zeta_example/pages/badge_example.dart'; import 'package:zeta_example/pages/color_example.dart'; +import 'package:zeta_example/pages/checkbox_example.dart'; import 'package:zeta_example/pages/grid_example.dart'; import 'package:zeta_example/pages/priority_pill_example.dart'; import 'package:zeta_example/pages/icons_example.dart'; @@ -29,6 +30,7 @@ final List components = [ Component(LabelExample.name, (context) => const LabelExample()), Component(BadgeExample.name, (context) => const BadgeExample()), Component(PriorityPillExample.name, (context) => const PriorityPillExample()), + Component(CheckBoxExample.name, (context) => const CheckBoxExample()), ]; class Home extends StatefulWidget { diff --git a/example/lib/main.dart b/example/lib/main.dart index 19c69098..5249b291 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,15 +1,47 @@ import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:zeta_example/theme_service.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; import 'home.dart'; -void main() => runApp(const ZetaExample()); +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + + final preferences = await SharedPreferences.getInstance(); + final themeService = SharedPrefsThemeService(preferences); + final themePreferences = await themeService.loadTheme(); + + runApp( + ZetaExample( + themeService: themeService, + initialThemeData: themePreferences.$1 ?? ZetaThemeData(), + initialThemeMode: themePreferences.$2 ?? ThemeMode.system, + initialContrast: themePreferences.$3 ?? ZetaContrast.aa, + ), + ); +} class ZetaExample extends StatelessWidget { - const ZetaExample({super.key}); + const ZetaExample({ + super.key, + required this.themeService, + required this.initialContrast, + required this.initialThemeMode, + required this.initialThemeData, + }); + + final ZetaThemeService themeService; + final ZetaContrast initialContrast; + final ThemeMode initialThemeMode; + final ZetaThemeData initialThemeData; @override Widget build(BuildContext context) { return ZetaProvider( + themeService: themeService, + initialContrast: initialContrast, + initialThemeData: initialThemeData, + initialThemeMode: initialThemeMode, builder: (context, themeData, themeMode) { final dark = themeData.colorsDark.toScheme(); final light = themeData.colorsLight.toScheme(); diff --git a/example/lib/pages/badge_example.dart b/example/lib/pages/badge_example.dart index 2d785973..1dbac310 100644 --- a/example/lib/pages/badge_example.dart +++ b/example/lib/pages/badge_example.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:zeta_flutter/src/utils/enums.dart'; import '../widgets.dart'; diff --git a/example/lib/pages/checkbox_example.dart b/example/lib/pages/checkbox_example.dart new file mode 100644 index 00000000..3d136332 --- /dev/null +++ b/example/lib/pages/checkbox_example.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class CheckBoxExample extends StatefulWidget { + static const String name = 'Checkbox'; + + const CheckBoxExample({Key? key}) : super(key: key); + + @override + State createState() => _CheckBoxExampleState(); +} + +class _CheckBoxExampleState extends State { + bool? isChecked = true; + bool isEnabled = true; + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: 'Checkbox', + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + ZetaCheckbox( + value: isChecked, isEnabled: isEnabled, onChanged: (value) => setState(() => isChecked = value)), + ElevatedButton( + child: const Text('Disable'), + onPressed: () => setState(() => isEnabled = !isEnabled), + ) + ], + ), + Row(children: [const Text('Sharp Checkbox Enabled')]), + getCheckBoxRow(isEnabled: true), + Row(children: [const Text('Sharp Checkbox Disabled')]), + getCheckBoxRow(isEnabled: false), + Row(children: [const Text('Rounded Checkbox Enabled')]), + getCheckBoxRow(isEnabled: true, isSharp: false), + Row(children: [const Text('Rounded Checkbox Disabled')]), + getCheckBoxRow(isEnabled: false, isSharp: false), + ], + ), + ), + ); + } +} + +Row getCheckBoxRow({required bool isEnabled, bool isSharp = true}) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + ZetaCheckbox( + value: true, + isEnabled: isEnabled, + label: 'Selected', + borderType: isSharp ? BorderType.sharp : BorderType.rounded, + onChanged: (value) => {}), + ZetaCheckbox( + value: false, + isEnabled: isEnabled, + label: 'Indeterminate', + borderType: isSharp ? BorderType.sharp : BorderType.rounded, + onChanged: (value) => {}), + ZetaCheckbox( + value: null, + borderType: isSharp ? BorderType.sharp : BorderType.rounded, + isEnabled: isEnabled, + onChanged: (value) => {}), + ]); +} diff --git a/example/lib/pages/priority_pill_example.dart b/example/lib/pages/priority_pill_example.dart index 1584b8ed..29f47a6a 100644 --- a/example/lib/pages/priority_pill_example.dart +++ b/example/lib/pages/priority_pill_example.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; import '../widgets.dart'; -import 'package:zeta_flutter/src/utils/enums.dart'; class PriorityPillExample extends StatelessWidget { static const String name = 'PriorityPill'; diff --git a/example/lib/pages/status_label_example.dart b/example/lib/pages/status_label_example.dart index 4b94cca4..40e8b9c5 100644 --- a/example/lib/pages/status_label_example.dart +++ b/example/lib/pages/status_label_example.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:zeta_flutter/src/utils/enums.dart'; import '../widgets.dart'; diff --git a/example/lib/pages/theme_color_switch.dart b/example/lib/pages/theme_color_switch.dart index a2ca12fc..cb4a29d8 100644 --- a/example/lib/pages/theme_color_switch.dart +++ b/example/lib/pages/theme_color_switch.dart @@ -1,32 +1,32 @@ import 'package:flutter/material.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; +late final appThemes = { + "default": ZetaThemeData(), + "teal": ZetaThemeData( + identifier: 'teal', + primary: ZetaColorBase.teal, + ), + "yellow": ZetaThemeData( + identifier: 'yellow', + primary: ZetaColorBase.yellow, + ), + "red": ZetaThemeData( + identifier: 'red', + primary: ZetaColorBase.red, + ), + "purple": ZetaThemeData( + identifier: 'purple', + primary: ZetaColorBase.purple, + ), +}; + class ZetaThemeColorSwitch extends StatelessWidget { ZetaThemeColorSwitch({super.key}); - late final _themes = { - "default": ZetaThemeData(), - "teal": ZetaThemeData( - identifier: 'teal', - primary: ZetaColorBase.teal, - ), - "yellow": ZetaThemeData( - identifier: 'yellow', - primary: ZetaColorBase.yellow, - ), - "red": ZetaThemeData( - identifier: 'red', - primary: ZetaColorBase.red, - ), - "purple": ZetaThemeData( - identifier: 'purple', - primary: ZetaColorBase.purple, - ), - }; - @override Widget build(BuildContext context) { - var zeta = Zeta.of(context); + final zeta = Zeta.of(context); ZetaColors primary(ZetaThemeData data) { if (zeta.brightness == Brightness.light) { @@ -44,9 +44,9 @@ class ZetaThemeColorSwitch extends StatelessWidget { alignment: Alignment.center, icon: SizedBox(width: 8), dropdownColor: zeta.colors.borderDisabled, - items: _themes.entries.map((e) { - var zetaColors = primary(_themes[e.key]!); - var color = zetaColors.primary; + items: appThemes.entries.map((e) { + final zetaColors = primary(appThemes[e.key]!); + final color = zetaColors.primary; return DropdownMenuItem( value: e.value.identifier, alignment: Alignment.center, @@ -58,7 +58,7 @@ class ZetaThemeColorSwitch extends StatelessWidget { ); }).toList(), onChanged: (value) { - final theme = _themes[value]; + final theme = appThemes[value]; if (theme != null) { ZetaProvider.of(context).updateThemeData(theme); } diff --git a/example/lib/pages/theme_constrast_switch.dart b/example/lib/pages/theme_constrast_switch.dart index 9d36c28f..2200ddeb 100644 --- a/example/lib/pages/theme_constrast_switch.dart +++ b/example/lib/pages/theme_constrast_switch.dart @@ -11,7 +11,7 @@ class ZetaThemeContrastSwitch extends StatelessWidget { @override Widget build(BuildContext context) { - var zeta = Zeta.of(context); + final zeta = Zeta.of(context); ZetaColors zetaColors(ZetaContrast contrast) { if (zeta.brightness == Brightness.light) { diff --git a/example/lib/pages/theme_mode_switch.dart b/example/lib/pages/theme_mode_switch.dart index 392d7e12..fb9a22e1 100644 --- a/example/lib/pages/theme_mode_switch.dart +++ b/example/lib/pages/theme_mode_switch.dart @@ -12,7 +12,7 @@ class ZetaThemeModeSwitch extends StatelessWidget { @override Widget build(BuildContext context) { - var zeta = Zeta.of(context); + final zeta = Zeta.of(context); ZetaColors zetaColors(ThemeMode mode) { if ((mode == ThemeMode.system && MediaQuery.of(context).platformBrightness == Brightness.light) || diff --git a/example/lib/theme_service.dart b/example/lib/theme_service.dart new file mode 100644 index 00000000..b25c0a45 --- /dev/null +++ b/example/lib/theme_service.dart @@ -0,0 +1,47 @@ +import 'package:flutter/src/material/app.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:zeta_example/pages/theme_color_switch.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class SharedPrefsThemeService extends ZetaThemeService { + SharedPrefsThemeService(this.preferences); + + final SharedPreferences preferences; + + @override + Future<(ZetaThemeData?, ThemeMode?, ZetaContrast?)> loadTheme() async { + final theme = preferences.getString('theme') ?? 'default'; + final themeData = appThemes[theme]; + + final modeString = preferences.getString('themeMode'); + final themeMode = modeString == 'light' + ? ThemeMode.light + : modeString == 'dark' + ? ThemeMode.dark + : ThemeMode.system; + + final contrastString = preferences.getString('contrast'); + final contrast = contrastString == 'aaa' ? ZetaContrast.aaa : ZetaContrast.aa; + + return (themeData, themeMode, contrast); + } + + @override + Future saveTheme({ + required ZetaThemeData themeData, + required ThemeMode themeMode, + required ZetaContrast contrast, + }) async { + await preferences.setString('theme', themeData.identifier); + + final modeString = themeMode == ThemeMode.light + ? 'light' + : themeMode == ThemeMode.dark + ? 'dark' + : 'system'; + await preferences.setString('themeMode', modeString); + + final contrastString = contrast == ZetaContrast.aaa ? 'aaa' : 'aa'; + await preferences.setString('contrast', contrastString); + } +} diff --git a/example/lib/widgets.dart b/example/lib/widgets.dart index 99c8da5d..769acbb7 100644 --- a/example/lib/widgets.dart +++ b/example/lib/widgets.dart @@ -70,7 +70,7 @@ class ExampleScaffold extends StatelessWidget { @override Widget build(BuildContext context) { - var theme = Theme.of(context); + final theme = Theme.of(context); final colors = theme.colorScheme; return Scaffold( @@ -101,7 +101,7 @@ class CodeExample extends StatelessWidget { @override Widget build(BuildContext context) { - var colors = Zeta.of(context).colors; + final colors = Zeta.of(context).colors; final widget = Container( color: colors.surfaceDisabled, padding: Dimensions.x4.square, diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift index e777c67d..b8e2b22f 100644 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,7 +6,9 @@ import FlutterMacOS import Foundation import path_provider_foundation +import shared_preferences_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index 0782b5c6..b99453dc 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -3,20 +3,27 @@ PODS: - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) EXTERNAL SOURCES: FlutterMacOS: :path: Flutter/ephemeral path_provider_foundation: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin + shared_preferences_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 diff --git a/example/pubspec.lock b/example/pubspec.lock deleted file mode 100644 index 7310c025..00000000 --- a/example/pubspec.lock +++ /dev/null @@ -1,385 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - accessibility_tools: - dependency: transitive - description: - name: accessibility_tools - sha256: "0a16adc8dfa3a7ebd38775135d86443011a65d4ecbb438913e4992b5d29135fe" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - async: - dependency: transitive - description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - characters: - dependency: transitive - description: - name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - clock: - dependency: transitive - description: - name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" - source: hosted - version: "1.1.1" - collection: - dependency: transitive - description: - name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 - url: "https://pub.dev" - source: hosted - version: "1.17.2" - crypto: - dependency: transitive - description: - name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab - url: "https://pub.dev" - source: hosted - version: "3.0.3" - device_frame: - dependency: transitive - description: - name: device_frame - sha256: afe76182aec178d171953d9b4a50a43c57c7cf3c77d8b09a48bf30c8fa04dd9d - url: "https://pub.dev" - source: hosted - version: "1.1.0" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" - source: hosted - version: "1.3.1" - ffi: - dependency: transitive - description: - name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - freezed_annotation: - dependency: transitive - description: - name: freezed_annotation - sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d - url: "https://pub.dev" - source: hosted - version: "2.4.1" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: "2ccd74480706e0a70a0e0dfa9543dede41bc11d0fe3b146a6ad7b7686f6b4407" - url: "https://pub.dev" - source: hosted - version: "11.1.4" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8 - url: "https://pub.dev" - source: hosted - version: "6.1.0" - http: - dependency: transitive - description: - name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" - source: hosted - version: "4.0.2" - inspector: - dependency: transitive - description: - name: inspector - sha256: "40ba0ac1c819c85139bfec9d1e283804581a8985c91f19d00e93212cf29226b1" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 - url: "https://pub.dev" - source: hosted - version: "4.8.1" - logging: - dependency: transitive - description: - name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" - url: "https://pub.dev" - source: hosted - version: "0.12.16" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" - url: "https://pub.dev" - source: hosted - version: "0.5.0" - meta: - dependency: transitive - description: - name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - path: - dependency: transitive - description: - name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" - url: "https://pub.dev" - source: hosted - version: "1.8.3" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa - url: "https://pub.dev" - source: hosted - version: "2.1.1" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" - url: "https://pub.dev" - source: hosted - version: "2.3.1" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" - url: "https://pub.dev" - source: hosted - version: "2.2.1" - platform: - dependency: transitive - description: - name: platform - sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" - url: "https://pub.dev" - source: hosted - version: "3.1.3" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 - url: "https://pub.dev" - source: hosted - version: "2.1.7" - resizable_widget: - dependency: transitive - description: - name: resizable_widget - sha256: db2919754b93f386b9b3fb15e9f48f6c9d6d41f00a24397629133c99df86606a - url: "https://pub.dev" - source: hosted - version: "1.0.5" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.dev" - source: hosted - version: "1.10.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 - url: "https://pub.dev" - source: hosted - version: "1.11.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - test_api: - dependency: transitive - description: - name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" - url: "https://pub.dev" - source: hosted - version: "0.6.0" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://pub.dev" - source: hosted - version: "1.3.2" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - web: - dependency: transitive - description: - name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 - url: "https://pub.dev" - source: hosted - version: "0.1.4-beta" - widgetbook: - dependency: "direct dev" - description: - name: widgetbook - sha256: "37bb71322ed2b024b4b321f9ac0791f6b4510a9abcd42a108c11bec97ac4688a" - url: "https://pub.dev" - source: hosted - version: "3.5.0" - win32: - dependency: transitive - description: - name: win32 - sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 - url: "https://pub.dev" - source: hosted - version: "5.1.1" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" - url: "https://pub.dev" - source: hosted - version: "1.0.3" - zeta_flutter: - dependency: "direct main" - description: - path: ".." - relative: true - source: path - version: "0.1.0+8" -sdks: - dart: ">=3.1.0 <4.0.0" - flutter: ">=3.10.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index f6c712a9..74d5c998 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -4,13 +4,14 @@ version: 0.0.1 publish_to: "none" environment: - sdk: ">=2.19.1 <3.0.0" + sdk: ">=3.0.1 <4.0.0" dependencies: flutter: sdk: flutter go_router: ^11.1.2 google_fonts: ^6.1.0 + shared_preferences: ^2.2.2 zeta_flutter: path: ../ diff --git a/example/test/badge_test.dart b/example/test/badge_test.dart index 72c57265..74eead34 100644 --- a/example/test/badge_test.dart +++ b/example/test/badge_test.dart @@ -1,6 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:zeta_flutter/src/utils/enums.dart'; import 'test_components.dart'; diff --git a/example/test/checkbox_test.dart b/example/test/checkbox_test.dart new file mode 100644 index 00000000..bc10b708 --- /dev/null +++ b/example/test/checkbox_test.dart @@ -0,0 +1,72 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:flutter/material.dart'; + +void main() { + group('ZetaCheckbox Tests', () { + testWidgets('Initializes with correct parameters', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidgetCB( + widget: ZetaCheckbox( + value: true, + onChanged: (value) {}, + borderType: BorderType.rounded, + label: 'Test Checkbox', + checkboxSize: Size(30, 30), + )), + ); + + final checkboxFinder = find.byType(ZetaCheckbox); + final ZetaCheckbox checkbox = tester.firstWidget(checkboxFinder); + + expect(checkbox.value, true); + expect(checkbox.borderType, BorderType.rounded); + expect(checkbox.label, 'Test Checkbox'); + expect(checkbox.checkboxSize, Size(30, 30)); + }); + + testWidgets('ZetaCheckbox changes state on tap', (WidgetTester tester) async { + bool? checkboxValue = true; + + await tester.pumpWidget( + TestWidgetCB( + widget: ZetaCheckbox( + value: checkboxValue, + onChanged: (value) { + checkboxValue = value; + }, + )), + ); + + await tester.tap(find.byType(ZetaCheckbox)); + await tester.pump(); + + expect(checkboxValue, false); + }); + }); +} + +class TestWidgetCB extends StatelessWidget { + final Widget widget; + + const TestWidgetCB({Key? key, required this.widget}); + + @override + Widget build(BuildContext context) { + return ZetaProvider( + builder: (context, theme, __) { + return Builder(builder: (context) { + return MaterialApp( + theme: ThemeData( + fontFamily: theme.fontFamily, + textTheme: ZetaText.textTheme, + ), + home: Scaffold( + body: widget, + ), + ); + }); + }, + ); + } +} diff --git a/example/widgetbook/components/badge_widgetbook.dart b/example/widgetbook/components/badge_widgetbook.dart index cf5a0544..558f175e 100644 --- a/example/widgetbook/components/badge_widgetbook.dart +++ b/example/widgetbook/components/badge_widgetbook.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_flutter/src/utils/enums.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; WidgetbookComponent badgeWidgetBook() { diff --git a/example/widgetbook/components/checkbox_widgetbook.dart b/example/widgetbook/components/checkbox_widgetbook.dart new file mode 100644 index 00000000..6909ee4e --- /dev/null +++ b/example/widgetbook/components/checkbox_widgetbook.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/checkbox_example.dart'; + +WidgetbookComponent checkboxWidgetBook() { + return WidgetbookComponent( + name: 'Checkbox', + useCases: [ + WidgetbookUseCase( + name: 'Checkbox (sharp)', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(top: 10), + child: getCheckBoxRow(isEnabled: true), + ), + ), + ), + WidgetbookUseCase( + name: 'Checkbox (rounded)', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(top: 10), + child: getCheckBoxRow(isEnabled: true, isSharp: false), + ), + ), + ), + WidgetbookUseCase( + name: 'Checkbox disabled (rounded)', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(top: 10), + child: getCheckBoxRow(isEnabled: false, isSharp: false), + ), + ), + ), + ], + ); +} diff --git a/example/widgetbook/components/priority_pill_widgetbook.dart b/example/widgetbook/components/priority_pill_widgetbook.dart index 89877ce7..a7df83a8 100644 --- a/example/widgetbook/components/priority_pill_widgetbook.dart +++ b/example/widgetbook/components/priority_pill_widgetbook.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:zeta_flutter/src/utils/enums.dart'; WidgetbookComponent priorityPillWidgetBook() { return WidgetbookComponent( diff --git a/example/widgetbook/components/status_label_widgetbook.dart b/example/widgetbook/components/status_label_widgetbook.dart index 976f182d..6ddaeaf9 100644 --- a/example/widgetbook/components/status_label_widgetbook.dart +++ b/example/widgetbook/components/status_label_widgetbook.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_example/pages/status_label_example.dart'; -import 'package:zeta_flutter/src/utils/enums.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; WidgetbookComponent statusLabelWidgetBook() { diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index da02347e..571dc8f6 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -3,6 +3,7 @@ import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; import 'components/badge_widgetbook.dart'; +import 'components/checkbox_widgetbook.dart'; import 'components/color_widgetbook.dart'; import 'components/grid_widgetbook.dart'; import 'components/indicator_widgetbook.dart'; @@ -31,7 +32,8 @@ class HotReload extends StatelessWidget { statusLabelWidgetBook(), badgeWidgetBook(), indicatorWidgetBook(), - priorityPillWidgetBook() + priorityPillWidgetBook(), + checkboxWidgetBook() ], ), ], diff --git a/ios/.gitignore b/ios/.gitignore deleted file mode 100644 index 0c885071..00000000 --- a/ios/.gitignore +++ /dev/null @@ -1,38 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -.generated/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/Generated.xcconfig -/Flutter/ephemeral/ -/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/ios/Assets/.gitkeep b/ios/Assets/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/ios/Classes/ZetaFlutterPlugin.swift b/ios/Classes/ZetaFlutterPlugin.swift deleted file mode 100644 index 8744bdc1..00000000 --- a/ios/Classes/ZetaFlutterPlugin.swift +++ /dev/null @@ -1,14 +0,0 @@ -import Flutter -import UIKit - -public class ZetaFlutterPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "zeta_flutter", binaryMessenger: registrar.messenger()) - let instance = ZetaFlutterPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - result("iOS " + UIDevice.current.systemVersion) - } -} diff --git a/ios/Classes/ZetaPlugin.swift b/ios/Classes/ZetaPlugin.swift deleted file mode 100644 index b8639360..00000000 --- a/ios/Classes/ZetaPlugin.swift +++ /dev/null @@ -1,14 +0,0 @@ -import Flutter -import UIKit - -public class ZetaPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "zeta", binaryMessenger: registrar.messenger()) - let instance = ZetaPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - result("iOS " + UIDevice.current.systemVersion) - } -} diff --git a/ios/zeta.podspec b/ios/zeta.podspec deleted file mode 100644 index 20d99c30..00000000 --- a/ios/zeta.podspec +++ /dev/null @@ -1,23 +0,0 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint zeta.podspec` to validate before publishing. -# -Pod::Spec.new do |s| - s.name = 'zeta' - s.version = '0.0.1' - s.summary = 'A new Flutter plugin project.' - s.description = <<-DESC -A new Flutter plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.dependency 'Flutter' - s.platform = :ios, '9.0' - - # Flutter.framework does not contain a i386 slice. - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } - s.swift_version = '5.0' -end diff --git a/ios/zeta_flutter.podspec b/ios/zeta_flutter.podspec deleted file mode 100644 index db2ecf5e..00000000 --- a/ios/zeta_flutter.podspec +++ /dev/null @@ -1,23 +0,0 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint zeta_flutter.podspec` to validate before publishing. -# -Pod::Spec.new do |s| - s.name = 'zeta_flutter' - s.version = '0.0.1' - s.summary = 'A new Flutter plugin project.' - s.description = <<-DESC -A new Flutter plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.dependency 'Flutter' - s.platform = :ios, '9.0' - - # Flutter.framework does not contain a i386 slice. - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } - s.swift_version = '5.0' -end diff --git a/lib/src/components/badge.dart b/lib/src/components/badge.dart index f776f1bc..3e563dcc 100644 --- a/lib/src/components/badge.dart +++ b/lib/src/components/badge.dart @@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../zeta_flutter.dart'; -import '../utils/enums.dart'; ///Zeta Badge class ZetaBadge extends StatelessWidget { diff --git a/lib/src/components/checkbox.dart b/lib/src/components/checkbox.dart new file mode 100644 index 00000000..f29c5333 --- /dev/null +++ b/lib/src/components/checkbox.dart @@ -0,0 +1,192 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '../../zeta_flutter.dart'; + +///Zeta Checkbox +class ZetaCheckbox extends StatelessWidget { + /// Constructs a [ZetaCheckbox]. + const ZetaCheckbox({ + required this.value, + required this.onChanged, + this.borderType = BorderType.sharp, + this.label, + this.labelStyle, + this.checkboxSize = const Size(25, 25), + this.selectedColor, + this.unselectedColor, + this.unselectedBorderColor, + this.unselectedBorderWidth = 2.5, + this.disabledColor, + this.isEnabled = true, + this.iconSize = 18.0, + super.key, + }) : assert(iconSize > 0, 'Icon size must be greater than 0'); + + /// Whether the checkbox is selected, unselected or null (indeterminate) + final bool? value; + + /// Called when the value of the checkbox should change. + final ValueChanged onChanged; + + /// The type of border to display + /// + /// defaults to sharp + final BorderType borderType; + + /// The label displayed next to the checkbox + final String? label; + + /// Style to use on the label + final TextStyle? labelStyle; + + ///Size of the checkbox + final Size checkboxSize; + + /// The color to use when this checkbox is checked. + final Color? selectedColor; + + ///Color of the checkbox when it's not selected + final Color? unselectedColor; + + ///Color of the border when the checkbox not selected + final Color? unselectedBorderColor; + + ///Width of the border when the checkbox is not selected + /// + /// Defaults to 2.5 + final double unselectedBorderWidth; + + ///Size of the icon displayed inside the checkbox + final double iconSize; + + ///If checkbox is enabled + /// + ///defaults to true + final bool isEnabled; + + ///Color of the checkbox when it's disabled + final Color? disabledColor; + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + final ValueNotifier isFocused = ValueNotifier(false); + + return FocusableActionDetector( + onFocusChange: (bool focus) => isFocused.value = focus, + child: GestureDetector( + onTap: _handleOnTap, + child: _buildCheckboxRow(theme, isFocused), + ), + ); + } + + void _handleOnTap() { + if (isEnabled) { + onChanged( + value == null + ? true + : value! + ? false + : null, + ); + } + } + + Widget _buildCheckboxRow( + Zeta theme, + ValueNotifier isFocused, + ) { + return Flex( + direction: Axis.horizontal, + mainAxisSize: MainAxisSize.min, + children: [ + _buildCheckboxContainer(theme, isFocused), + if (label != null) ...[ + Flexible( + child: Padding( + padding: const EdgeInsets.only(left: Dimensions.s), + child: Text( + label!, + style: labelStyle ?? ZetaText.zetaTitleMedium, + ), + ), + ), + ], + ], + ); + } + + Widget _buildCheckboxContainer(Zeta theme, ValueNotifier isFocused) { + return ValueListenableBuilder( + valueListenable: isFocused, + builder: (context, focused, child) { + return Container( + decoration: BoxDecoration( + boxShadow: _getBoxShadow(theme, focused), + color: _getCheckboxBackgroundColor(theme), + border: Border.all( + color: _getCheckboxBorderColor(theme), + width: unselectedBorderWidth, + ), + borderRadius: BorderRadius.circular( + borderType == BorderType.rounded ? 4.0 : 0.0, + ), + ), + width: checkboxSize.width, + height: checkboxSize.height, + child: _getCheckboxIcon(theme), + ); + }, + ); + } + + List _getBoxShadow(Zeta theme, bool focused) { + if (!focused) return []; + return [ + BoxShadow( + spreadRadius: 3, + color: theme.colors.surfaceSelectedHovered, + ), + ]; + } + + Widget _getCheckboxIcon(Zeta theme) { + if (value == null) return const SizedBox.shrink(); + return Icon( + value! ? Icons.check : Icons.remove, + color: isEnabled ? theme.colors.white : theme.colors.textDisabled, + size: iconSize, + ); + } + + Color _getCheckboxBackgroundColor(Zeta theme) { + if (!isEnabled) return disabledColor ?? theme.colors.surfaceDisabled; + if (value == null) return unselectedColor ?? theme.colors.surfaceSecondary; + return selectedColor ?? theme.colors.primary; + } + + Color _getCheckboxBorderColor(Zeta theme) { + if (!isEnabled || value != null) return Colors.transparent; + return unselectedBorderColor ?? theme.colors.borderDefault; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('value', value)) + ..add(ObjectFlagProperty>.has('onChanged', onChanged)) + ..add(EnumProperty('borderType', borderType)) + ..add(StringProperty('label', label)) + ..add(DiagnosticsProperty('labelStyle', labelStyle)) + ..add(DiagnosticsProperty('checkboxSize', checkboxSize)) + ..add(ColorProperty('selectedColor', selectedColor)) + ..add(ColorProperty('unselectedColor', unselectedColor)) + ..add(ColorProperty('unselectedBorderColor', unselectedBorderColor)) + ..add(DoubleProperty('unselectedBorderWidth', unselectedBorderWidth)) + ..add(ColorProperty('disabledColor', disabledColor)) + ..add(DiagnosticsProperty('isEnabled', isEnabled)) + ..add(DoubleProperty('iconSize', iconSize)); + } +} diff --git a/lib/src/components/priority_pill.dart b/lib/src/components/priority_pill.dart index d90754bb..49e24f31 100644 --- a/lib/src/components/priority_pill.dart +++ b/lib/src/components/priority_pill.dart @@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../zeta_flutter.dart'; -import '../utils/enums.dart'; ///Zeta Priority Pill class ZetaPriorityPill extends StatelessWidget { diff --git a/lib/src/components/status_label.dart b/lib/src/components/status_label.dart index 5b80b823..629aa351 100644 --- a/lib/src/components/status_label.dart +++ b/lib/src/components/status_label.dart @@ -1,7 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../zeta_flutter.dart'; -import '../utils/enums.dart'; ///Zeta Status Label Colors class ZetaStatusLabelColors { diff --git a/lib/src/theme/colors.dart b/lib/src/theme/colors.dart index 955df4d7..9abdc4f3 100644 --- a/lib/src/theme/colors.dart +++ b/lib/src/theme/colors.dart @@ -218,11 +218,11 @@ class ZetaColors { // Text / icons. + /// {@template zeta-color-dark} /// Default text /icon color. /// /// Defaults to `ZetaColors.cool.90`. /// - /// {@template zeta-color-dark} /// Color swatches are inverted if [ZetaColors.brightness] is Dark. /// {@endtemplate} Color get textDefault => cool.shade90; @@ -252,11 +252,11 @@ class ZetaColors { /// {@macro zeta-color-dark} Color get textInverse => cool.shade20; + /// {@template zeta-color-dark} /// Default icon color. /// /// Defaults to `ZetaColors.cool.90`. /// - /// {@template zeta-color-dark} /// Color swatches are inverted if [ZetaColors.brightness] is Dark. /// {@endtemplate} Color get iconDefault => textDefault; diff --git a/lib/src/theme/theme_service.dart b/lib/src/theme/theme_service.dart index bbc63ee5..84b243ad 100644 --- a/lib/src/theme/theme_service.dart +++ b/lib/src/theme/theme_service.dart @@ -1,17 +1,25 @@ +import 'package:flutter/material.dart'; + +import 'contrast.dart'; import 'theme_data.dart'; /// `ZetaThemeService` is an abstract class. /// It provides the structure for loading and saving themes in Zeta application. abstract class ZetaThemeService { - /// Loads the application's theme. + /// Asynchronously load the theme data. /// - /// `loadTheme` is a method to retrieve the current theme data. + /// This method returns a `Future` that when complete will produce a + /// tuple of `ZetaThemeData`, `ThemeMode`, and `ZetaContrast`. /// - /// Returns a `Future` that completes with the `ZetaThemeData` object - /// that represents the current theme. - - Future loadTheme(); + /// `ZetaThemeData` describes the colors that are used by a theme. + /// + /// `ThemeMode` determines the brightness of the system. + /// + /// `ZetaContrast` defines different contrast styles to use across the application. + /// + /// Returns a Future `(ZetaThemeData?, ThemeMode?, ZetaContrast?)`. + Future<(ZetaThemeData?, ThemeMode?, ZetaContrast?)> loadTheme(); /// Saves the provided theme data as the application's theme. /// @@ -21,5 +29,9 @@ abstract class ZetaThemeService { /// /// Returns a `Future` that completes when the theme data has been successfully saved. - Future saveTheme(ZetaThemeData themeData); + Future saveTheme({ + required ZetaThemeData themeData, + required ThemeMode themeMode, + required ZetaContrast contrast, + }); } diff --git a/lib/src/zeta.dart b/lib/src/zeta.dart index cf8a7c42..e28de7e3 100644 --- a/lib/src/zeta.dart +++ b/lib/src/zeta.dart @@ -248,17 +248,6 @@ class ZetaProviderState extends State with Diagnosticable, Widgets // Apply the initial contrast to the theme data. _themeData = widget.initialThemeData.apply(contrast: _contrast); - - // Load theme data from themeService if available. - unawaited( - widget.themeService?.loadTheme().then((value) { - if (value != null) { - setState(() { - _themeData = value; - }); - } - }), - ); } /// Clean up function to be called when this object is removed from the tree. @@ -332,6 +321,7 @@ class ZetaProviderState extends State with Diagnosticable, Widgets void updateThemeMode(ThemeMode themeMode) { setState(() { _themeMode = themeMode; + _saveThemeChange(); }); } @@ -339,7 +329,7 @@ class ZetaProviderState extends State with Diagnosticable, Widgets void updateThemeData(ZetaThemeData data) { setState(() { _themeData = data.apply(contrast: _contrast); - unawaited(widget.themeService?.saveTheme(data)); + _saveThemeChange(); }); } @@ -348,9 +338,20 @@ class ZetaProviderState extends State with Diagnosticable, Widgets setState(() { _contrast = contrast; _themeData = _themeData.apply(contrast: contrast); + _saveThemeChange(); }); } + void _saveThemeChange() { + unawaited( + widget.themeService?.saveTheme( + themeData: _themeData, + themeMode: _themeMode, + contrast: _contrast, + ), + ); + } + @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 793070b8..067bdf9c 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -2,6 +2,7 @@ library zeta_flutter; export 'src/components/badge.dart'; +export 'src/components/checkbox.dart'; export 'src/components/grid.dart'; export 'src/components/indicator.dart'; export 'src/components/priority_pill.dart'; @@ -15,6 +16,8 @@ export 'src/theme/color_swatch.dart'; export 'src/theme/constants.dart'; export 'src/theme/contrast.dart'; export 'src/theme/theme_data.dart'; +export 'src/theme/theme_service.dart'; export 'src/tokens.dart'; +export 'src/utils/enums.dart'; export 'src/utils/extensions.dart'; export 'src/zeta.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 5d8f8d99..cca23b5a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.0+9 +version: 0.1.1+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. From 8f621dc82bd58ace9c994057420cdb1f41a74200 Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:08:20 +0200 Subject: [PATCH 12/41] Component ZetaAvatar (#32) * add empty avatar example page; upgrade packages * add icons * [automated commit] lint format and import sort * create avatar component with examples * create ZetaIndicator component with examples * fix value * fix & improve; add badges (indicators) * add more comments * add factory constructors for the different types * add widgetbook * add avatar to widgetbook * [automated commit] lint format and import sort * Badge (#29) * initial * Badge * fix test * [automated commit] lint format and import sort * change default border type * fix test * [automated commit] lint format and import sort * [automated commit] lint format and import sort * [automated commit] lint format and import sort * fix example * fix sizing * add foreground colors * [automated commit] lint format and import sort --------- Co-authored-by: github-actions * [automated commit] lint format and import sort * replace photo with image * [automated commit] lint format and import sort --------- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> --- CHANGELOG.md | 101 +++- example/lib/home.dart | 2 + example/lib/pages/avatar_example.dart | 556 ++++++++++++++++++ .../Flutter/GeneratedPluginRegistrant.swift | 2 + .../components/avatar_widgetbook.dart | 53 ++ example/widgetbook/widgetbook.dart | 2 + lib/src/assets/fonts/zeta-icons-other.ttf | Bin 0 -> 1088 bytes lib/src/components/avatar.dart | 413 +++++++++++++ lib/src/icons.dart | 4 + lib/zeta_flutter.dart | 1 + pubspec.yaml | 6 +- zeta-icons-other.json | 1 + 12 files changed, 1132 insertions(+), 9 deletions(-) create mode 100644 example/lib/pages/avatar_example.dart create mode 100644 example/widgetbook/components/avatar_widgetbook.dart create mode 100644 lib/src/assets/fonts/zeta-icons-other.ttf create mode 100644 lib/src/components/avatar.dart create mode 100644 zeta-icons-other.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 41d0a4f2..c0d3476b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,108 @@ -## [0.1.1+2] - 2023-12-13 +## [0.1.1+3] - 2023-12-15 ### :flying_saucer: Other Changes -- [`063386f`](https://github.com/zebratechnologies/zeta-flutter/commit/063386f83490bf3bfb6d26fc6a95dd445006d656) - some sizings were not exactly as shown in Figma ([#33](https://github.com/zebratechnologies/zeta-flutter/pull/33)) +- [`5f0a33e`](https://github.com/zebratechnologies/zeta-flutter/commit/5f0a33e8e3b92de83d83170f267e6cd3f5fca068) - Merge from zebradevs ([#27](https://github.com/zebratechnologies/zeta-flutter/pull/27)) -* . +* Merge from zebradevs + +* spelling and finals * [automated commit] lint format and import sort --------- -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* -- [`1c8ca4c`](https://github.com/zebratechnologies/zeta-flutter/commit/1c8ca4c4b5dbd8378710a18765303a6d37472cf0) - Merge from zebradevs ([#27](https://github.com/zebratechnologies/zeta-flutter/pull/27)) +Co-authored-by: github-actions *(commit by [@thelukewalton](https://github.com/thelukewalton))* +- [`b20aef1`](https://github.com/zebratechnologies/zeta-flutter/commit/b20aef109944e6cfc02db9b0041e7a6009c9e52e) - Component ZetaAvatar ([#32](https://github.com/zebratechnologies/zeta-flutter/pull/32)) -* Merge from zebradevs +* add empty avatar example page; upgrade packages + +* add icons + +* [automated commit] lint format and import sort + +* create avatar component with examples + +* create ZetaIndicator component with examples + +* fix value + +* fix & improve; add badges (indicators) + +* add more comments + +* add factory constructors for the different types + +* add widgetbook -* spelling and finals +* add avatar to widgetbook + +* [automated commit] lint format and import sort + +* Badge ([#29](https://github.com/zebratechnologies/zeta-flutter/pull/29)) + +* initial + +* Badge + +* fix test + +* [automated commit] lint format and import sort + +* change default border type + +* fix test + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* fix example + +* fix sizing + +* add foreground colors + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions + +* [automated commit] lint format and import sort + +* replace photo with image * [automated commit] lint format and import sort --------- +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions +Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + +## [0.1.1+2] - 2023-12-13 +### :flying_saucer: Other Changes +- [`063386f`](https://github.com/zebratechnologies/zeta-flutter/commit/063386f83490bf3bfb6d26fc6a95dd445006d656) - some sizings were not exactly as shown in Figma ([#33](https://github.com/zebratechnologies/zeta-flutter/pull/33)) + +* . + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`1c8ca4c`](https://github.com/zebratechnologies/zeta-flutter/commit/1c8ca4c4b5dbd8378710a18765303a6d37472cf0) - Merge from zebradevs ([#27](https://github.com/zebratechnologies/zeta-flutter/pull/27)) + +* Merge from zebradevs + +* spelling and finals + +* [automated commit] lint format and import sort + +--------- + Co-authored-by: github-actions *(commit by [@thelukewalton](https://github.com/thelukewalton))* @@ -534,4 +618,5 @@ Introduced license details for third-party libraries used in the project. MIT li - Initial setup -[0.1.1+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+9...0.1.1+2 \ No newline at end of file +[0.1.1+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+9...0.1.1+2 +[0.1.1+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+2...0.1.1+3 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 93c883ff..de83c76d 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:zeta_example/pages/avatar_example.dart'; import 'package:zeta_example/pages/badge_example.dart'; import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/checkbox_example.dart'; @@ -25,6 +26,7 @@ final List components = [ Component(SpacingExample.name, (context) => const SpacingExample()), Component(TypographyExample.name, (context) => const TypographyExample()), Component(ColorExample.name, (context) => const ColorExample()), + Component(AvatarExample.name, (context) => const AvatarExample()), Component(IconsExample.name, (context) => const IconsExample()), Component(IndicatorExample.name, (context) => const IndicatorExample()), Component(LabelExample.name, (context) => const LabelExample()), diff --git a/example/lib/pages/avatar_example.dart b/example/lib/pages/avatar_example.dart new file mode 100644 index 00000000..a3bef6e5 --- /dev/null +++ b/example/lib/pages/avatar_example.dart @@ -0,0 +1,556 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class AvatarExample extends StatelessWidget { + static const String name = 'Avatar'; + + const AvatarExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: AvatarExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + avatarImageExample, + const SizedBox(height: 25), + avatarInitialsExample, + const SizedBox(height: 25), + avatarImageWithBadgeExample, + const SizedBox(height: 25), + avatarInitialsWithBadgeExample, + const SizedBox(height: 25), + avatarImageWithSpecialStatusExample, + const SizedBox(height: 25), + avatarInitialsWithSpecialStatusExample, + ], + ), + ), + ); + }, + ); + } + + static Widget get avatarImageExample => Column( + children: [ + Text( + 'ZetaAvatar.image', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size); + final padding = (ZetaAvatar.getSizePixels(size) - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image(size: size), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ); + + static Widget get avatarInitialsExample => Column( + children: [ + Text( + 'ZetaAvatar.initials', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size); + final padding = (ZetaAvatar.getSizePixels(size) - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + name: 'Antony Brothers', + showStatus: true, + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ); + + static Widget get avatarImageWithBadgeExample => Column( + children: [ + Text( + 'ZetaAvatar.image with badge', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size) + 6; + final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ); + + static Widget get avatarInitialsWithBadgeExample => Column( + children: [ + Text( + 'ZetaAvatar.initials with badge', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size) + 6; + final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + name: 'Antony Brothers', + showStatus: true, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ); + + static Widget get avatarImageWithSpecialStatusExample => Column( + children: [ + Text( + 'ZetaAvatar.image with special status', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size) + 6; + final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ); + + static Widget get avatarInitialsWithSpecialStatusExample => Column( + children: [ + Text( + 'ZetaAvatar.initials with special status', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size) + 6; + final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + name: 'Antony Brothers', + showStatus: true, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ); + + static ZetaIndicatorSize _getBadgeSize(ZetaAvatarSize size) { + switch (size) { + case ZetaAvatarSize.xl: + return ZetaIndicatorSize.large; + case ZetaAvatarSize.l: + return ZetaIndicatorSize.large; + case ZetaAvatarSize.m: + return ZetaIndicatorSize.large; + case ZetaAvatarSize.s: + return ZetaIndicatorSize.medium; + case ZetaAvatarSize.xs: + return ZetaIndicatorSize.small; + } + } + + static ZetaIndicatorSize _getSpecialStatusSize(ZetaAvatarSize size) { + switch (size) { + case ZetaAvatarSize.xl: + return ZetaIndicatorSize.large; + case ZetaAvatarSize.l: + return ZetaIndicatorSize.medium; + case ZetaAvatarSize.m: + return ZetaIndicatorSize.medium; + case ZetaAvatarSize.s: + return ZetaIndicatorSize.medium; + case ZetaAvatarSize.xs: + return ZetaIndicatorSize.small; + } + } +} diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift index b8e2b22f..eefcc6d7 100644 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,8 +7,10 @@ import Foundation import path_provider_foundation import shared_preferences_foundation +import sqflite func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) } diff --git a/example/widgetbook/components/avatar_widgetbook.dart b/example/widgetbook/components/avatar_widgetbook.dart new file mode 100644 index 00000000..f6535d15 --- /dev/null +++ b/example/widgetbook/components/avatar_widgetbook.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/avatar_example.dart'; + +WidgetbookComponent avatarWidgetBook() { + return WidgetbookComponent( + name: 'Avatar', + useCases: [ + WidgetbookUseCase( + name: 'Photo', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: AvatarExample.avatarImageExample, + ), + ), + WidgetbookUseCase( + name: 'Initials', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: AvatarExample.avatarInitialsExample, + ), + ), + WidgetbookUseCase( + name: 'Photo with badge', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: AvatarExample.avatarImageWithBadgeExample, + ), + ), + WidgetbookUseCase( + name: 'Initials with badge', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: AvatarExample.avatarInitialsWithBadgeExample, + ), + ), + WidgetbookUseCase( + name: 'Photo with special status', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: AvatarExample.avatarImageWithSpecialStatusExample, + ), + ), + WidgetbookUseCase( + name: 'Initials with special status', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: AvatarExample.avatarInitialsWithSpecialStatusExample, + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 571dc8f6..67b82828 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; +import 'components/avatar_widgetbook.dart'; import 'components/badge_widgetbook.dart'; import 'components/checkbox_widgetbook.dart'; import 'components/color_widgetbook.dart'; @@ -33,6 +34,7 @@ class HotReload extends StatelessWidget { badgeWidgetBook(), indicatorWidgetBook(), priorityPillWidgetBook(), + avatarWidgetBook(), checkboxWidgetBook() ], ), diff --git a/lib/src/assets/fonts/zeta-icons-other.ttf b/lib/src/assets/fonts/zeta-icons-other.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ba841bf80e29331887cdca0c3d6550b2310c5adb GIT binary patch literal 1088 zcma)5O=}ZT6g_V~k~Rrxk=THwI@Yw6EMkahwICRR6be>D)ojfqohE@~W=v8@7eW?- zE))x{1YNjwA^rdtS?R`&{s9qJ#kEU`=gmw@3@&`(y?f5N_r81Q&IAHL6ho-U-M(`v zKX*#cQ2D@Jt#?c}S^4@H5GnGz4YTLc&XY?!(`X;;Z9IJYhI~N&s%e?K%b%X9fRZ3z zZ&C=C)Q{vh$r~jq$naXqDil4YFX2~a)n4e@47l9+Fqwxqum79v3#qlycAgjrp zqR+Q1>2VELX(Q}c;ZMLg!ua=iObsVkjDI9G=1tx!AQ&|#HCASQX5-3+7xKRvGsYuz z$lNG9gUGM16;>`Rg-$0Hl1t&Z2!|HM`L)7oR;;clD7$W1?p&!f$YfMxGJ{e{6n(Mm zR%5YTI-RRl?inV9PfgA1^Dg*tRNg@%QvPY7w8&sJ-|BW zC3$RLkEx;OaGr&3)nC-`hsNV>11O+^8)g8Ns z78`J2qgS!Iy_RDe`D_6dSga|X(q$lzEDBTcQ*_5_?6=J>c9`10KH4zRor>9X?7q>k zY^!VbtzDybU~JW$ZO5^**z_v(S*yVdY_GnFKJ6~G8V-1Fd97|UQg)T)oV@>=Klp#0 Fe*o3hoJ{}# literal 0 HcmV?d00001 diff --git a/lib/src/components/avatar.dart b/lib/src/components/avatar.dart new file mode 100644 index 00000000..2eae9b55 --- /dev/null +++ b/lib/src/components/avatar.dart @@ -0,0 +1,413 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '../../zeta_flutter.dart'; + +/// [ZetaAvatar] type +enum ZetaAvatarType { + /// [image] shows a picture or a placeholder + image, + + /// [initials] shows one or two letters + initials, +} + +/// [ZetaAvatar] size +enum ZetaAvatarSize { + /// [xl] 64 pixels + xl, + + /// [l] 48 pixels + l, + + /// [m] 40 pixels + m, + + /// [s] 32 pixels + s, + + /// [xs] 24 pixels + xs, +} + +/// ZetaAvatar component +class ZetaAvatar extends StatelessWidget { + /// Constructor for [ZetaAvatar] + /// [image] and [imageUrl] are used with [type] `ZetaAvatarType.image` + /// [initials] and [name] are used with [type] `ZetaAvatarType.initials` + /// If none provided, a placeholder is displayed, which defaults to `ZetaIcons.avatar`, + /// but can be customized via [placeholderIcon] and [placeholderColor]. + ZetaAvatar({ + super.key, + required this.type, + this.size = ZetaAvatarSize.xl, + this.image, + this.imageUrl, + this.initials, + this.name, + this.backgroundColor, + this.placeholderIcon, + this.placeholderColor, + this.showStatus = false, + this.statusPrimaryColor, + this.statusSecondaryColor, + this.specialStatus, + this.badge, + }) { + _sizePixels = getSizePixels(size); + _borderSize = _getBorderSize(size); + _initialsToShow = + initials?.isEmpty ?? true ? _getInitialsFromName(name) : initials!.substring(0, initials!.length > 1 ? 2 : 1); + } + + /// Constructor for [ZetaAvatar] of type `image` + factory ZetaAvatar.image({ + ZetaAvatarSize size = ZetaAvatarSize.xl, + ImageProvider? image, + String? imageUrl, + String? initials, + String? name, + Color? backgroundColor, + Icon? placeholderIcon, + Color? placeholderColor, + bool showStatus = false, + Color? statusPrimaryColor, + Color? statusSecondaryColor, + ZetaIndicator? specialStatus, + ZetaIndicator? badge, + }) => + ZetaAvatar( + type: ZetaAvatarType.image, + size: size, + image: image, + imageUrl: imageUrl, + initials: initials, + name: name, + backgroundColor: backgroundColor, + placeholderIcon: placeholderIcon, + placeholderColor: placeholderColor, + showStatus: showStatus, + statusPrimaryColor: statusPrimaryColor, + statusSecondaryColor: statusSecondaryColor, + specialStatus: specialStatus, + badge: badge, + ); + + /// Constructor for [ZetaAvatar] of type `initials` + factory ZetaAvatar.initials({ + ZetaAvatarSize size = ZetaAvatarSize.xl, + ImageProvider? image, + String? imageUrl, + String? initials, + String? name, + Color? backgroundColor, + Icon? placeholderIcon, + Color? placeholderColor, + bool showStatus = false, + Color? statusPrimaryColor, + Color? statusSecondaryColor, + ZetaIndicator? specialStatus, + ZetaIndicator? badge, + }) => + ZetaAvatar( + type: ZetaAvatarType.initials, + size: size, + image: image, + imageUrl: imageUrl, + initials: initials, + name: name, + backgroundColor: backgroundColor, + placeholderIcon: placeholderIcon, + placeholderColor: placeholderColor, + showStatus: showStatus, + statusPrimaryColor: statusPrimaryColor, + statusSecondaryColor: statusSecondaryColor, + specialStatus: specialStatus, + badge: badge, + ); + + /// The type of the [ZetaAvatar] - image or initials + final ZetaAvatarType type; + + /// The size of the [ZetaAvatar] + final ZetaAvatarSize size; + + /// The `ImageProvider` for the type `image` + final ImageProvider? image; + + /// The URL for the type `image` + final String? imageUrl; + + /// The initials for the type `initials` + final String? initials; + + /// Initials could be retrieved from `name` + final String? name; + + /// Background color. + final Color? backgroundColor; + + /// Placeholder icon + final Icon? placeholderIcon; + + /// Placeholder color + final Color? placeholderColor; + + /// Shows border around the avatar + /// See also [statusPrimaryColor] and [statusSecondaryColor] + final bool showStatus; + + /// Color for the outer border, if [showStatus] is `true` + final Color? statusPrimaryColor; + + /// Color for the inner border, if [showStatus] is `true` + final Color? statusSecondaryColor; + + /// Show [ZetaIndicator] at the lower right corner + final ZetaIndicator? specialStatus; + + /// Show [ZetaIndicator] at the upper right corner + final ZetaIndicator? badge; + + late final double _sizePixels; + late final double _borderSize; + late final String _initialsToShow; + + @override + Widget build(BuildContext context) { + final zetaColors = Zeta.of(context).colors; + + final innerContent = _InnerContent( + type: type, + size: size, + sizePixels: _sizePixels, + borderSize: _borderSize, + image: image, + imageUrl: imageUrl, + initials: _initialsToShow, + showStatus: showStatus, + placeholderIcon: placeholderIcon, + placeholderColor: placeholderColor, + ); + + return Stack( + children: [ + if (showStatus) + Container( + margin: EdgeInsets.all(badge == null && specialStatus == null ? 0 : 3), + width: _sizePixels, + height: _sizePixels, + decoration: BoxDecoration( + border: Border.all( + color: statusPrimaryColor ?? zetaColors.positive, + width: _borderSize, + ), + borderRadius: BorderRadius.circular(64), + ), + child: Container( + width: _sizePixels - _borderSize * 2, + height: _sizePixels - _borderSize * 2, + decoration: BoxDecoration( + color: type == ZetaAvatarType.initials && _initialsToShow.isNotEmpty + ? backgroundColor ?? zetaColors.surfaceHovered + : null, + border: Border.all( + color: statusSecondaryColor ?? zetaColors.surfacePrimary, + width: _borderSize, + ), + borderRadius: BorderRadius.circular(64), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(64), + clipBehavior: Clip.hardEdge, + child: innerContent, + ), + ), + ) + else + Container( + margin: EdgeInsets.all(badge == null && specialStatus == null ? 0 : 3), + width: _sizePixels, + height: _sizePixels, + decoration: BoxDecoration( + color: backgroundColor ?? zetaColors.surfaceHovered, + borderRadius: BorderRadius.circular(64), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(64), + clipBehavior: Clip.hardEdge, + child: innerContent, + ), + ), + if (badge != null) + Positioned( + right: 1, + child: badge!, + ), + if (specialStatus != null) + Positioned( + right: 1, + bottom: 1, + child: specialStatus!, + ), + ], + ); + } + + /// Returns the size of [ZetaAvatarSize] in pixels + static double getSizePixels(ZetaAvatarSize size) { + switch (size) { + case ZetaAvatarSize.xl: + return 64; + case ZetaAvatarSize.l: + return 48; + case ZetaAvatarSize.m: + return 40; + case ZetaAvatarSize.s: + return 32; + case ZetaAvatarSize.xs: + return 24; + } + } + + double _getBorderSize(ZetaAvatarSize size) { + switch (size) { + case ZetaAvatarSize.xl: + return 2; + case ZetaAvatarSize.l: + return 2; + case ZetaAvatarSize.m: + return 1.67; + case ZetaAvatarSize.s: + return 1.33; + case ZetaAvatarSize.xs: + return 1; + } + } + + String _getInitialsFromName(String? name) { + if (name == null) return ''; + final List nameParts = name.split(RegExp(r'\W+'))..removeWhere((item) => item.isEmpty); + if (nameParts.isEmpty) return ''; + return (nameParts.length > 1 + ? nameParts[0].substring(0, 1) + nameParts[1].substring(0, 1) + : nameParts[0].length > 1 + ? nameParts[0].substring(0, 2) + : nameParts[0]) + .toUpperCase(); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', type)) + ..add(DiagnosticsProperty('size', size)) + ..add(DiagnosticsProperty('image', image)) + ..add(DiagnosticsProperty('imageUrl', imageUrl)) + ..add(DiagnosticsProperty('initials', initials)) + ..add(DiagnosticsProperty('name', name)) + ..add(DiagnosticsProperty('showStatus', showStatus)) + ..add(DiagnosticsProperty('specialStatus', specialStatus)) + ..add(DiagnosticsProperty('badge', badge)) + ..add(DiagnosticsProperty('placeholderIcon', placeholderIcon)) + ..add(DiagnosticsProperty('backgroundColor', backgroundColor)) + ..add(DiagnosticsProperty('placeholderColor', placeholderColor)) + ..add(DiagnosticsProperty('statusPrimaryColor', statusPrimaryColor)) + ..add(DiagnosticsProperty('statusSecondaryColor', statusSecondaryColor)); + } +} + +class _InnerContent extends StatelessWidget { + const _InnerContent({ + required this.type, + required this.size, + required this.sizePixels, + required this.borderSize, + required this.initials, + this.image, + this.imageUrl, + this.showStatus = false, + this.placeholderIcon, + this.placeholderColor, + }); + + final ZetaAvatarType type; + final ZetaAvatarSize size; + final double sizePixels; + final double borderSize; + final String initials; + final ImageProvider? image; + final String? imageUrl; + final bool showStatus; + final Icon? placeholderIcon; + final Color? placeholderColor; + + @override + Widget build(BuildContext context) { + final placeholder = IconTheme( + data: IconThemeData( + color: placeholderColor ?? Zeta.of(context).colors.cool, + size: showStatus ? sizePixels - borderSize * 4 : sizePixels, + ), + child: placeholderIcon ?? const Icon(ZetaIcons.avatar), + ); + + switch (type) { + case ZetaAvatarType.image: + return image == null + ? imageUrl == null + ? placeholder + : CachedNetworkImage( + imageUrl: imageUrl!, + fit: BoxFit.cover, + placeholder: (_, __) => placeholder, + errorWidget: (_, __, ___) => placeholder, + ) + : Image(image: image!, fit: BoxFit.cover); + case ZetaAvatarType.initials: + return initials.isEmpty + ? placeholder + : Center( + child: Text( + size == ZetaAvatarSize.xs ? initials.substring(0, 1) : initials, + style: TextStyle( + fontSize: _getFontSize(size), + letterSpacing: -0.5, + ), + ), + ); + } + } + + double _getFontSize(ZetaAvatarSize size) { + switch (size) { + case ZetaAvatarSize.xl: + return 28; + case ZetaAvatarSize.l: + return 24; + case ZetaAvatarSize.m: + return 20; + case ZetaAvatarSize.s: + return 16; + case ZetaAvatarSize.xs: + return 16; + } + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', type)) + ..add(DiagnosticsProperty('size', size)) + ..add(DiagnosticsProperty('sizePixels', sizePixels)) + ..add(DiagnosticsProperty('borderSize', borderSize)) + ..add(DiagnosticsProperty('image', image)) + ..add(DiagnosticsProperty('imageUrl', imageUrl)) + ..add(DiagnosticsProperty('initials', initials)) + ..add(DiagnosticsProperty('showStatus', showStatus)) + ..add(DiagnosticsProperty('placeholderIcon', placeholderIcon)) + ..add(DiagnosticsProperty('placeholderColor', placeholderColor)); + } +} diff --git a/lib/src/icons.dart b/lib/src/icons.dart index 682fc135..f11ecfdf 100644 --- a/lib/src/icons.dart +++ b/lib/src/icons.dart @@ -6,6 +6,7 @@ class ZetaIcons { ZetaIcons._(); static const String _familyRound = 'zeta-icons-round'; static const String _familySharp = 'zeta-icons-sharp'; + static const String _familyOther = 'zeta-icons-other'; static const String _package = 'zeta_flutter'; // round @@ -1005,4 +1006,7 @@ class ZetaIcons { static const IconData star_sharp = IconData(0xe1e2, fontFamily: _familySharp, fontPackage: _package); static const IconData toggle_off_sharp = IconData(0xe1e3, fontFamily: _familySharp, fontPackage: _package); static const IconData toggle_on_sharp = IconData(0xe1e4, fontFamily: _familySharp, fontPackage: _package); + + // other icons + static const IconData avatar = IconData(0xe900, fontFamily: _familyOther, fontPackage: _package); } diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 067bdf9c..cb6f2e54 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -1,6 +1,7 @@ /// Zebra Design System (Zeta) - Flutter Component Library library zeta_flutter; +export 'src/components/avatar.dart'; export 'src/components/badge.dart'; export 'src/components/checkbox.dart'; export 'src/components/grid.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index cca23b5a..5761b492 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+2 +version: 0.1.1+3 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. @@ -22,6 +22,7 @@ environment: flutter: ">=3.7.0" dependencies: + cached_network_image: ^3.3.0 flutter: sdk: flutter @@ -46,4 +47,7 @@ flutter: - family: zeta-icons-sharp fonts: - asset: lib/src/assets/fonts/zeta-icons-sharp.ttf + - family: zeta-icons-other + fonts: + - asset: lib/src/assets/fonts/zeta-icons-other.ttf uses-material-design: true diff --git a/zeta-icons-other.json b/zeta-icons-other.json new file mode 100644 index 00000000..eec695e8 --- /dev/null +++ b/zeta-icons-other.json @@ -0,0 +1 @@ +{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M512 640c106.080 0 192-85.92 192-192s-85.92-192-192-192c-106.080 0-192 85.92-192 192s85.92 192 192 192zM512 736c-128.16 0-384 64.32-384 192v96h768v-96c0-127.68-255.84-192-384-192z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Group 5"],"colorPermutations":{"25525525518489991":[{}]}},"attrs":[{}],"properties":{"order":771,"id":0,"name":"Avatar","prevSize":32,"code":59648},"setIdx":0,"setId":0,"iconIdx":0}],"height":1024,"metadata":{"name":"icons"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icons","majorVersion":2,"minorVersion":4},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"flutter":true,"showMetadata":false,"showMetrics":false,"showVersion":true,"showSelector":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon","name":"icomoon"},"historySize":50,"showCodes":true,"gridSize":16,"showGrid":false,"showLiga":true}} \ No newline at end of file From 1268c92c7e0057cd166c40bc9ccd53ccf80c2fef Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Fri, 15 Dec 2023 19:54:41 +0200 Subject: [PATCH 13/41] App bar (#35) * create ZetaAppBar in four variants with example screens * [automated commit] lint format and import sort * remove Flexible * rename * titleIcon should be of type Icon instead of Widget --------- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions --- CHANGELOG.md | 218 +++++++++++++----- example/lib/home.dart | 21 +- .../app_bar_example/app_bar_example.dart | 111 +++++++++ .../app_bar_example/default_app_bar.dart | 24 ++ .../app_bar_example/negative_app_bar.dart | 26 +++ .../app_bar_example/positive_app_bar.dart | 25 ++ .../app_bar_example/warning_app_bar.dart | 25 ++ lib/src/components/system_banner.dart | 162 +++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 10 files changed, 549 insertions(+), 66 deletions(-) create mode 100644 example/lib/pages/app_bar_example/app_bar_example.dart create mode 100644 example/lib/pages/app_bar_example/default_app_bar.dart create mode 100644 example/lib/pages/app_bar_example/negative_app_bar.dart create mode 100644 example/lib/pages/app_bar_example/positive_app_bar.dart create mode 100644 example/lib/pages/app_bar_example/warning_app_bar.dart create mode 100644 lib/src/components/system_banner.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d3476b..1ceddc10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,84 +1,173 @@ -## [0.1.1+3] - 2023-12-15 +## [0.1.1+4] - 2023-12-15 ### :flying_saucer: Other Changes -- [`5f0a33e`](https://github.com/zebratechnologies/zeta-flutter/commit/5f0a33e8e3b92de83d83170f267e6cd3f5fca068) - Merge from zebradevs ([#27](https://github.com/zebratechnologies/zeta-flutter/pull/27)) +- [`8f621dc`](https://github.com/zebratechnologies/zeta-flutter/commit/8f621dc82bd58ace9c994057420cdb1f41a74200) - Component ZetaAvatar ([#32](https://github.com/zebratechnologies/zeta-flutter/pull/32)) -* Merge from zebradevs +* add empty avatar example page; upgrade packages -* spelling and finals +* add icons + +* [automated commit] lint format and import sort + +* create avatar component with examples + +* create ZetaIndicator component with examples + +* fix value + +* fix & improve; add badges (indicators) + +* add more comments + +* add factory constructors for the different types + +* add widgetbook + +* add avatar to widgetbook + +* [automated commit] lint format and import sort + +* Badge ([#29](https://github.com/zebratechnologies/zeta-flutter/pull/29)) + +* initial + +* Badge + +* fix test + +* [automated commit] lint format and import sort + +* change default border type + +* fix test + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* fix example + +* fix sizing + +* add foreground colors * [automated commit] lint format and import sort --------- -Co-authored-by: github-actions *(commit by [@thelukewalton](https://github.com/thelukewalton))* -- [`b20aef1`](https://github.com/zebratechnologies/zeta-flutter/commit/b20aef109944e6cfc02db9b0041e7a6009c9e52e) - Component ZetaAvatar ([#32](https://github.com/zebratechnologies/zeta-flutter/pull/32)) +Co-authored-by: github-actions -* add empty avatar example page; upgrade packages - -* add icons - -* [automated commit] lint format and import sort - -* create avatar component with examples - -* create ZetaIndicator component with examples - -* fix value - -* fix & improve; add badges (indicators) - -* add more comments - -* add factory constructors for the different types - -* add widgetbook - -* add avatar to widgetbook - -* [automated commit] lint format and import sort - -* Badge ([#29](https://github.com/zebratechnologies/zeta-flutter/pull/29)) - -* initial - -* Badge - -* fix test - -* [automated commit] lint format and import sort - -* change default border type - -* fix test - -* [automated commit] lint format and import sort - -* [automated commit] lint format and import sort - -* [automated commit] lint format and import sort - -* fix example - -* fix sizing - -* add foreground colors +* [automated commit] lint format and import sort + +* replace photo with image + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions +Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`350adec`](https://github.com/zebratechnologies/zeta-flutter/commit/350adecf4b0498afc6a476a653d2223a7cb74e0f) - App bar ([#35](https://github.com/zebratechnologies/zeta-flutter/pull/35)) + +* create ZetaAppBar in four variants with example screens * [automated commit] lint format and import sort ---------- +* remove Flexible -Co-authored-by: github-actions +* rename -* [automated commit] lint format and import sort - -* replace photo with image - -* [automated commit] lint format and import sort +* titleIcon should be of type Icon instead of Widget --------- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + +## [0.1.1+3] - 2023-12-15 +### :flying_saucer: Other Changes +- [`5f0a33e`](https://github.com/zebratechnologies/zeta-flutter/commit/5f0a33e8e3b92de83d83170f267e6cd3f5fca068) - Merge from zebradevs ([#27](https://github.com/zebratechnologies/zeta-flutter/pull/27)) + +* Merge from zebradevs + +* spelling and finals + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@thelukewalton](https://github.com/thelukewalton))* +- [`b20aef1`](https://github.com/zebratechnologies/zeta-flutter/commit/b20aef109944e6cfc02db9b0041e7a6009c9e52e) - Component ZetaAvatar ([#32](https://github.com/zebratechnologies/zeta-flutter/pull/32)) + +* add empty avatar example page; upgrade packages + +* add icons + +* [automated commit] lint format and import sort + +* create avatar component with examples + +* create ZetaIndicator component with examples + +* fix value + +* fix & improve; add badges (indicators) + +* add more comments + +* add factory constructors for the different types + +* add widgetbook + +* add avatar to widgetbook + +* [automated commit] lint format and import sort + +* Badge ([#29](https://github.com/zebratechnologies/zeta-flutter/pull/29)) + +* initial + +* Badge + +* fix test + +* [automated commit] lint format and import sort + +* change default border type + +* fix test + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* fix example + +* fix sizing + +* add foreground colors + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions + +* [automated commit] lint format and import sort + +* replace photo with image + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -619,4 +708,5 @@ Introduced license details for third-party libraries used in the project. MIT li - Initial setup [0.1.1+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+9...0.1.1+2 -[0.1.1+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+2...0.1.1+3 \ No newline at end of file +[0.1.1+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+2...0.1.1+3 +[0.1.1+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+3...0.1.1+4 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index de83c76d..22fa03fe 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -1,5 +1,10 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:zeta_example/pages/app_bar_example/app_bar_example.dart'; +import 'package:zeta_example/pages/app_bar_example/default_app_bar.dart'; +import 'package:zeta_example/pages/app_bar_example/negative_app_bar.dart'; +import 'package:zeta_example/pages/app_bar_example/positive_app_bar.dart'; +import 'package:zeta_example/pages/app_bar_example/warning_app_bar.dart'; import 'package:zeta_example/pages/avatar_example.dart'; import 'package:zeta_example/pages/badge_example.dart'; import 'package:zeta_example/pages/color_example.dart'; @@ -32,6 +37,12 @@ final List components = [ Component(LabelExample.name, (context) => const LabelExample()), Component(BadgeExample.name, (context) => const BadgeExample()), Component(PriorityPillExample.name, (context) => const PriorityPillExample()), + Component(AppBarExample.name, (context) => const AppBarExample(), [ + Component(DefaultAppBarExample.name, (context) => const DefaultAppBarExample()), + Component(PositiveAppBarExample.name, (context) => const PositiveAppBarExample()), + Component(WarningAppBarExample.name, (context) => const WarningAppBarExample()), + Component(NegativeAppBarExample.name, (context) => const NegativeAppBarExample()), + ]), Component(CheckBoxExample.name, (context) => const CheckBoxExample()), ]; @@ -46,13 +57,21 @@ final GoRouter router = GoRouter( routes: [ GoRoute( path: '/', + name: 'Home', builder: (_, __) => const Home(), routes: [ ...components.map( (e) => GoRoute( path: e.name, + name: e.name, builder: (_, __) => e.pageBuilder.call(_), - routes: e.children.map((f) => GoRoute(path: f.name, builder: (_, __) => f.pageBuilder(_))).toList(), + routes: e.children + .map((f) => GoRoute( + path: f.name, + name: f.name, + builder: (_, __) => f.pageBuilder(_), + )) + .toList(), ), ) ], diff --git a/example/lib/pages/app_bar_example/app_bar_example.dart b/example/lib/pages/app_bar_example/app_bar_example.dart new file mode 100644 index 00000000..01deaac8 --- /dev/null +++ b/example/lib/pages/app_bar_example/app_bar_example.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/home.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'default_app_bar.dart'; +import '../../widgets.dart'; +import 'negative_app_bar.dart'; +import 'positive_app_bar.dart'; +import 'warning_app_bar.dart'; + +class AppBarExample extends StatelessWidget { + static const String name = 'AppBar'; + + const AppBarExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: AppBarExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.symmetric(vertical: Dimensions.m), + child: Column( + children: [ + ZetaSystemBanner( + type: ZetaSystemBannerType.defaultAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + ), + const SizedBox(height: Dimensions.m), + ZetaSystemBanner( + type: ZetaSystemBannerType.positiveAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + titleIcon: Icon(ZetaIcons.info_round), + ), + const SizedBox(height: Dimensions.m), + ZetaSystemBanner( + type: ZetaSystemBannerType.warningAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + centerTitle: true, + ), + const SizedBox(height: Dimensions.m), + ZetaSystemBanner( + type: ZetaSystemBannerType.negativeAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + titleIcon: Icon(ZetaIcons.info_round), + centerTitle: true, + ), + const SizedBox(height: Dimensions.m), + ZetaSystemBanner( + type: ZetaSystemBannerType.defaultAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + actions: [ + IconButton( + onPressed: () => router.pushNamed(DefaultAppBarExample.name), + icon: Icon(ZetaIcons.chevron_right_round), + ), + ], + ), + const SizedBox(height: Dimensions.m), + ZetaSystemBanner( + type: ZetaSystemBannerType.positiveAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + titleIcon: Icon(ZetaIcons.info_round), + actions: [ + IconButton( + onPressed: () => router.pushNamed(PositiveAppBarExample.name), + icon: Icon(ZetaIcons.chevron_right_round), + ), + ], + ), + const SizedBox(height: Dimensions.m), + ZetaSystemBanner( + type: ZetaSystemBannerType.warningAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + centerTitle: true, + actions: [ + IconButton( + onPressed: () => router.pushNamed(WarningAppBarExample.name), + icon: Icon(ZetaIcons.chevron_right_round), + ), + ], + ), + const SizedBox(height: Dimensions.m), + ZetaSystemBanner( + type: ZetaSystemBannerType.negativeAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + titleIcon: Icon(ZetaIcons.info_round), + centerTitle: true, + actions: [ + IconButton( + onPressed: () => router.pushNamed(NegativeAppBarExample.name), + icon: Icon(ZetaIcons.chevron_right_round), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/example/lib/pages/app_bar_example/default_app_bar.dart b/example/lib/pages/app_bar_example/default_app_bar.dart new file mode 100644 index 00000000..6a24ddbe --- /dev/null +++ b/example/lib/pages/app_bar_example/default_app_bar.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:zeta_example/home.dart'; + +class DefaultAppBarExample extends StatelessWidget { + static const String name = 'DefaultAppBar'; + + const DefaultAppBarExample({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: ZetaSystemBanner( + type: ZetaSystemBannerType.defaultAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + leading: IconButton( + onPressed: () => router.pop(), + icon: Icon(ZetaIcons.chevron_left_round), + ), + ), + ); + } +} diff --git a/example/lib/pages/app_bar_example/negative_app_bar.dart b/example/lib/pages/app_bar_example/negative_app_bar.dart new file mode 100644 index 00000000..51d4cf7d --- /dev/null +++ b/example/lib/pages/app_bar_example/negative_app_bar.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:zeta_example/home.dart'; + +class NegativeAppBarExample extends StatelessWidget { + static const String name = 'NegativeAppBar'; + + const NegativeAppBarExample({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: ZetaSystemBanner( + type: ZetaSystemBannerType.negativeAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + titleIcon: Icon(ZetaIcons.info_round), + centerTitle: true, + leading: IconButton( + onPressed: () => router.pop(), + icon: Icon(ZetaIcons.chevron_left_round), + ), + ), + ); + } +} diff --git a/example/lib/pages/app_bar_example/positive_app_bar.dart b/example/lib/pages/app_bar_example/positive_app_bar.dart new file mode 100644 index 00000000..f2377a7d --- /dev/null +++ b/example/lib/pages/app_bar_example/positive_app_bar.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:zeta_example/home.dart'; + +class PositiveAppBarExample extends StatelessWidget { + static const String name = 'PositiveAppBar'; + + const PositiveAppBarExample({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: ZetaSystemBanner( + type: ZetaSystemBannerType.positiveAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + titleIcon: Icon(ZetaIcons.info_round), + leading: IconButton( + onPressed: () => router.pop(), + icon: Icon(ZetaIcons.chevron_left_round), + ), + ), + ); + } +} diff --git a/example/lib/pages/app_bar_example/warning_app_bar.dart b/example/lib/pages/app_bar_example/warning_app_bar.dart new file mode 100644 index 00000000..22db2f9a --- /dev/null +++ b/example/lib/pages/app_bar_example/warning_app_bar.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:zeta_example/home.dart'; + +class WarningAppBarExample extends StatelessWidget { + static const String name = 'WarningAppBar'; + + const WarningAppBarExample({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: ZetaSystemBanner( + type: ZetaSystemBannerType.warningAppBar, + automaticallyImplyLeading: false, + title: Text('Banner Title'), + centerTitle: true, + leading: IconButton( + onPressed: () => router.pop(), + icon: Icon(ZetaIcons.chevron_left_round), + ), + ), + ); + } +} diff --git a/lib/src/components/system_banner.dart b/lib/src/components/system_banner.dart new file mode 100644 index 00000000..96fda9ed --- /dev/null +++ b/lib/src/components/system_banner.dart @@ -0,0 +1,162 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import '../../zeta_flutter.dart'; + +/// [ZetaSystemBanner] type +enum ZetaSystemBannerType { + /// blue background + defaultAppBar, + + /// green background + positiveAppBar, + + /// brown/yellow background + warningAppBar, + + /// red background + negativeAppBar, +} + +/// ZetaSystemBanner component +class ZetaSystemBanner extends StatelessWidget implements PreferredSizeWidget { + /// Constructor for [ZetaSystemBanner] + const ZetaSystemBanner({ + super.key, + this.type = ZetaSystemBannerType.defaultAppBar, + this.leading, + this.centerTitle = false, + this.actions, + this.title, + this.titleIcon, + this.titleSpacing, + this.systemOverlayStyle, + this.automaticallyImplyLeading = false, + }); + + /// The type of the [ZetaSystemBanner] + final ZetaSystemBannerType type; + + /// AppBar leading + final Widget? leading; + + /// AppBar title + final Widget? title; + + /// Icon to place next to the AppBar title, on the left side. + final Icon? titleIcon; + + /// AppBar centerTitle + final bool centerTitle; + + /// AppBar titleSpacing + final double? titleSpacing; + + /// AppBar automaticallyImplyLeading. Default is `true` + final bool automaticallyImplyLeading; + + /// AppBar actions + final List? actions; + + /// AppBar systemOverlayStyle + final SystemUiOverlayStyle? systemOverlayStyle; + + @override + Widget build(BuildContext context) { + final foregroundColor = _foregroundColorFromType(context, type); + return AppBar( + titleSpacing: titleSpacing, + centerTitle: centerTitle, + backgroundColor: _backgroundColorFromType(context, type), + foregroundColor: foregroundColor, + systemOverlayStyle: systemOverlayStyle ?? + SystemUiOverlayStyle.dark.copyWith( + statusBarIconBrightness: _statusBarIconBrightness(context, type), + ), + leading: leading, + automaticallyImplyLeading: automaticallyImplyLeading, + title: DefaultTextStyle( + style: TextStyle( + fontSize: 16, + height: 1.5, + fontWeight: FontWeight.w500, + color: foregroundColor, + overflow: TextOverflow.ellipsis, + ), + child: titleIcon == null + ? title ?? const SizedBox() + : Row( + mainAxisAlignment: centerTitle ? MainAxisAlignment.center : MainAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(right: title == null ? 0 : 8), + child: titleIcon, + ), + Flexible( + child: title ?? const SizedBox(), + ), + ], + ), + ), + actions: actions ?? (leading != null && titleIcon != null ? [const SizedBox(width: 40)] : null), + ); + } + + Color _backgroundColorFromType(BuildContext context, ZetaSystemBannerType type) { + final themeMode = Zeta.of(context).themeMode; + switch (type) { + case ZetaSystemBannerType.defaultAppBar: + return ZetaColorBase.blue.shade60; + case ZetaSystemBannerType.positiveAppBar: + return themeMode == ThemeMode.dark ? ZetaColorBase.green.shade70 : ZetaColorBase.green; + case ZetaSystemBannerType.warningAppBar: + return themeMode == ThemeMode.dark ? ZetaColorBase.orange.shade30 : ZetaColorBase.orange.shade60; + case ZetaSystemBannerType.negativeAppBar: + return ZetaColorBase.red.shade60; + } + } + + Color _foregroundColorFromType(BuildContext context, ZetaSystemBannerType type) { + switch (type) { + case ZetaSystemBannerType.defaultAppBar: + return ZetaColorBase.white; + case ZetaSystemBannerType.positiveAppBar: + return ZetaColorBase.white; + case ZetaSystemBannerType.warningAppBar: + return ZetaColorBase.black; + case ZetaSystemBannerType.negativeAppBar: + return ZetaColorBase.white; + } + } + + Brightness _statusBarIconBrightness(BuildContext context, ZetaSystemBannerType type) { + switch (type) { + case ZetaSystemBannerType.defaultAppBar: + return Brightness.light; + case ZetaSystemBannerType.positiveAppBar: + return Brightness.light; + case ZetaSystemBannerType.warningAppBar: + return Brightness.dark; + case ZetaSystemBannerType.negativeAppBar: + return Brightness.light; + } + } + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', type)) + ..add(DiagnosticsProperty('leading', leading)) + ..add(DiagnosticsProperty('title', title)) + ..add(DiagnosticsProperty('titleIcon', titleIcon)) + ..add(DiagnosticsProperty('centerTitle', centerTitle)) + ..add(DiagnosticsProperty('titleSpacing', titleSpacing)) + ..add(DiagnosticsProperty('automaticallyImplyLeading', automaticallyImplyLeading)) + ..add(DiagnosticsProperty?>('actions', actions)) + ..add(DiagnosticsProperty('systemOverlayStyle', systemOverlayStyle)); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index cb6f2e54..dd4bfc6e 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -9,6 +9,7 @@ export 'src/components/indicator.dart'; export 'src/components/priority_pill.dart'; export 'src/components/spacing.dart'; export 'src/components/status_label.dart'; +export 'src/components/system_banner.dart'; export 'src/components/text.dart'; export 'src/icons.dart'; export 'src/theme/color_extensions.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 5761b492..e8668658 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+3 +version: 0.1.1+4 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. From 354040c91731f53f9186ce0cbce341706dc30b3a Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Mon, 18 Dec 2023 13:28:38 +0200 Subject: [PATCH 14/41] Workcloud indicators (#34) * initial * workcloud indicator * typo * . * [automated commit] lint format and import sort * . * . * . * [automated commit] lint format and import sort * [automated commit] lint format and import sort * add default values * [automated commit] lint format and import sort --------- Co-authored-by: github-actions --- CHANGELOG.md | 78 ++- example/lib/home.dart | 3 + example/lib/pages/status_label_example.dart | 4 +- .../pages/workcloud_indicator_example.dart | 99 ++++ example/pubspec.lock | 537 ++++++++++++++++++ example/test/workcloud_indicator_test.dart | 42 ++ .../components/status_label_widgetbook.dart | 2 +- .../workcloud_indicator_widgetbook.dart | 67 +++ example/widgetbook/widgetbook.dart | 2 + lib/src/components/status_label.dart | 51 +- lib/src/components/workcloud_indicator.dart | 275 +++++++++ lib/src/utils/enums.dart | 29 + lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 14 files changed, 1141 insertions(+), 51 deletions(-) create mode 100644 example/lib/pages/workcloud_indicator_example.dart create mode 100644 example/pubspec.lock create mode 100644 example/test/workcloud_indicator_test.dart create mode 100644 example/widgetbook/components/workcloud_indicator_widgetbook.dart create mode 100644 lib/src/components/workcloud_indicator.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ceddc10..43c8c79a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,52 @@ +## [0.1.1+5] - 2023-12-18 +### :flying_saucer: Other Changes +- [`1268c92`](https://github.com/zebratechnologies/zeta-flutter/commit/1268c92c7e0057cd166c40bc9ccd53ccf80c2fef) - App bar ([#35](https://github.com/zebratechnologies/zeta-flutter/pull/35)) + +* create ZetaAppBar in four variants with example screens + +* [automated commit] lint format and import sort + +* remove Flexible + +* rename + +* titleIcon should be of type Icon instead of Widget + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`077d161`](https://github.com/zebratechnologies/zeta-flutter/commit/077d16138d5d3f579fbc2bfcba3048b1c5d28afc) - Workcloud indicators ([#34](https://github.com/zebratechnologies/zeta-flutter/pull/34)) + +* initial + +* workcloud indicator + +* typo + +* . + +* [automated commit] lint format and import sort + +* . + +* . + +* . + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* add default values + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + ## [0.1.1+4] - 2023-12-15 ### :flying_saucer: Other Changes - [`8f621dc`](https://github.com/zebratechnologies/zeta-flutter/commit/8f621dc82bd58ace9c994057420cdb1f41a74200) - Component ZetaAvatar ([#32](https://github.com/zebratechnologies/zeta-flutter/pull/32)) @@ -71,19 +120,19 @@ Co-authored-by: github-actions Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - [`350adec`](https://github.com/zebratechnologies/zeta-flutter/commit/350adecf4b0498afc6a476a653d2223a7cb74e0f) - App bar ([#35](https://github.com/zebratechnologies/zeta-flutter/pull/35)) -* create ZetaAppBar in four variants with example screens - -* [automated commit] lint format and import sort - -* remove Flexible - -* rename - -* titleIcon should be of type Icon instead of Widget - ---------- - -Co-authored-by: Atanas Yordanov +* create ZetaAppBar in four variants with example screens + +* [automated commit] lint format and import sort + +* remove Flexible + +* rename + +* titleIcon should be of type Icon instead of Widget + +--------- + +Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -709,4 +758,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+9...0.1.1+2 [0.1.1+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+2...0.1.1+3 -[0.1.1+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+3...0.1.1+4 \ No newline at end of file +[0.1.1+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+3...0.1.1+4 +[0.1.1+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+4...0.1.1+5 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 22fa03fe..3d1eeba6 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -16,6 +16,7 @@ import 'package:zeta_example/pages/indicator_example.dart'; import 'package:zeta_example/pages/spacing_example.dart'; import 'package:zeta_example/pages/status_label_example.dart'; import 'package:zeta_example/pages/typography_example.dart'; +import 'package:zeta_example/pages/workcloud_indicator_example.dart'; import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; @@ -23,6 +24,7 @@ class Component { final String name; final WidgetBuilder pageBuilder; final List children; + Component(this.name, this.pageBuilder, [this.children = const []]); } @@ -37,6 +39,7 @@ final List components = [ Component(LabelExample.name, (context) => const LabelExample()), Component(BadgeExample.name, (context) => const BadgeExample()), Component(PriorityPillExample.name, (context) => const PriorityPillExample()), + Component(WorkcloudIndicatorExample.name, (context) => const WorkcloudIndicatorExample()), Component(AppBarExample.name, (context) => const AppBarExample(), [ Component(DefaultAppBarExample.name, (context) => const DefaultAppBarExample()), Component(PositiveAppBarExample.name, (context) => const PositiveAppBarExample()), diff --git a/example/lib/pages/status_label_example.dart b/example/lib/pages/status_label_example.dart index 40e8b9c5..fa4d384a 100644 --- a/example/lib/pages/status_label_example.dart +++ b/example/lib/pages/status_label_example.dart @@ -23,7 +23,7 @@ class LabelExample extends StatelessWidget { statusLabelExampleRow(WidgetSeverity.negative), statusLabelExampleRow( WidgetSeverity.custom, - colors: ZetaStatusLabelColors(accentColor: Colors.blue, backgroundColor: Colors.blue.shade50), + colors: ZetaWidgetColor(foregroundColor: Colors.blue, backgroundColor: Colors.blue.shade50), ), ], ), @@ -32,7 +32,7 @@ class LabelExample extends StatelessWidget { } } -Widget statusLabelExampleRow(WidgetSeverity type, {ZetaStatusLabelColors? colors}) { +Widget statusLabelExampleRow(WidgetSeverity type, {ZetaWidgetColor? colors}) { return Padding( padding: EdgeInsets.all(10), child: diff --git a/example/lib/pages/workcloud_indicator_example.dart b/example/lib/pages/workcloud_indicator_example.dart new file mode 100644 index 00000000..95a6259e --- /dev/null +++ b/example/lib/pages/workcloud_indicator_example.dart @@ -0,0 +1,99 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class WorkcloudIndicatorExample extends StatelessWidget { + static const String name = 'WorkcloudIndicator'; + + const WorkcloudIndicatorExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: WorkcloudIndicatorExample.name, + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ZetaWorkcloudIndicator( + label: 'Test Status Badge', + ), + ], + ), + SizedBox(height: 10), + Row(children: [ZetaWorkcloudIndicator.status(label: 'Status')]), + SizedBox(height: 10), + Row(children: [ZetaWorkcloudIndicator.status(label: 'In Progress')]), + SizedBox(height: 10), + Row(children: [ZetaWorkcloudIndicator.status(label: 'Reviewed')]), + SizedBox(height: 10), + Row(children: [ZetaWorkcloudIndicator.status(label: 'Resolved')]), + SizedBox(height: 100), + Padding( + padding: EdgeInsets.all(10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [Text('Medium'), Text('Small'), Text('X-Small')], + ), + ), + workcloudIndicatorExampleRow('Urgent', 'U', ZetaWorkcloudIndicatorType.urgent), + SizedBox(height: 10), + workcloudIndicatorExampleRow('High', '1', ZetaWorkcloudIndicatorType.high), + SizedBox(height: 10), + workcloudIndicatorExampleRow('Medium', '2', ZetaWorkcloudIndicatorType.medium), + SizedBox(height: 10), + workcloudIndicatorExampleRow('Low', '3', ZetaWorkcloudIndicatorType.low), + SizedBox(height: 10), + workcloudIndicatorExampleRow('Custom', '4', ZetaWorkcloudIndicatorType.custom, + colors: ZetaWidgetColor(backgroundColor: Colors.purple, foregroundColor: Colors.purple.shade50)), + ], + ), + ), + ); + } +} + +List workcloudIndicatorStatusRow(String label) { + return [ + Row(children: [ZetaWorkcloudIndicator.status(label: label)]), + SizedBox(height: 10) + ]; +} + +Widget workcloudIndicatorExampleRow(String label, String index, ZetaWorkcloudIndicatorType type, + {ZetaWidgetColor? colors}) { + return Padding( + padding: EdgeInsets.all(10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ZetaWorkcloudIndicator.priorityPill( + index: index, + label: label, + priorityType: type, + prioritySize: ZetaWidgetSize.large, + customColors: colors, + ), + ZetaWorkcloudIndicator.priorityPill( + index: index, + label: label, + prioritySize: ZetaWidgetSize.medium, + priorityType: type, + customColors: colors, + ), + ZetaWorkcloudIndicator.priorityPill( + index: index, + label: label, + priorityType: type, + customColors: colors, + ), + ], + ), + ); +} diff --git a/example/pubspec.lock b/example/pubspec.lock new file mode 100644 index 00000000..8e749b4c --- /dev/null +++ b/example/pubspec.lock @@ -0,0 +1,537 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + accessibility_tools: + dependency: transitive + description: + name: accessibility_tools + sha256: "0a16adc8dfa3a7ebd38775135d86443011a65d4ecbb438913e4992b5d29135fe" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + cached_network_image: + dependency: transitive + description: + name: cached_network_image + sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f + url: "https://pub.dev" + source: hosted + version: "3.3.0" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" + source: hosted + version: "1.17.2" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + device_frame: + dependency: transitive + description: + name: device_frame + sha256: afe76182aec178d171953d9b4a50a43c57c7cf3c77d8b09a48bf30c8fa04dd9d + url: "https://pub.dev" + source: hosted + version: "1.1.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + url: "https://pub.dev" + source: hosted + version: "3.3.1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + url: "https://pub.dev" + source: hosted + version: "2.4.1" + go_router: + dependency: "direct main" + description: + name: go_router + sha256: "2ccd74480706e0a70a0e0dfa9543dede41bc11d0fe3b146a6ad7b7686f6b4407" + url: "https://pub.dev" + source: hosted + version: "11.1.4" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8 + url: "https://pub.dev" + source: hosted + version: "6.1.0" + http: + dependency: transitive + description: + name: http + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + inspector: + dependency: transitive + description: + name: inspector + sha256: "40ba0ac1c819c85139bfec9d1e283804581a8985c91f19d00e93212cf29226b1" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + platform: + dependency: transitive + description: + name: platform + sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" + url: "https://pub.dev" + source: hosted + version: "3.1.3" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 + url: "https://pub.dev" + source: hosted + version: "2.1.7" + resizable_widget: + dependency: transitive + description: + name: resizable_widget + sha256: db2919754b93f386b9b3fb15e9f48f6c9d6d41f00a24397629133c99df86606a + url: "https://pub.dev" + source: hosted + version: "1.0.5" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" + url: "https://pub.dev" + source: hosted + version: "2.3.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a + url: "https://pub.dev" + source: hosted + version: "2.3.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 + url: "https://pub.dev" + source: hosted + version: "2.5.0+2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" + source: hosted + version: "0.6.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: "22c94e5ad1e75f9934b766b53c742572ee2677c56bc871d850a57dad0f82127f" + url: "https://pub.dev" + source: hosted + version: "4.2.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" + widgetbook: + dependency: "direct dev" + description: + name: widgetbook + sha256: "37bb71322ed2b024b4b321f9ac0791f6b4510a9abcd42a108c11bec97ac4688a" + url: "https://pub.dev" + source: hosted + version: "3.5.0" + win32: + dependency: transitive + description: + name: win32 + sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 + url: "https://pub.dev" + source: hosted + version: "5.1.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + zeta_flutter: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "0.1.1+4" +sdks: + dart: ">=3.1.0 <4.0.0" + flutter: ">=3.10.0" diff --git a/example/test/workcloud_indicator_test.dart b/example/test/workcloud_indicator_test.dart new file mode 100644 index 00000000..1186849d --- /dev/null +++ b/example/test/workcloud_indicator_test.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import 'test_components.dart'; + +void main() { + group('ZetaWorkcloud', () { + testWidgets('ZetaWorkcloud creates status badge', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaWorkcloudIndicator.status(label: 'Test Label'), + ), + ); + expect(find.byType(ZetaWorkcloudIndicator), findsOneWidget); + }); + }); + + testWidgets('ZetaWorkcloud creates priority pill', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaWorkcloudIndicator.priorityPill(index: '1'), + ), + ); + expect(find.text('1'), findsOneWidget); + }); + + testWidgets('ZetaWorkcloud custom colors', (WidgetTester tester) async { + final customColor = ZetaWidgetColor(backgroundColor: Colors.pink, foregroundColor: Colors.pink); + await tester.pumpWidget( + TestWidget( + widget: ZetaWorkcloudIndicator.priorityPill( + index: '1', + priorityType: ZetaWorkcloudIndicatorType.custom, + customColors: customColor, + ), + ), + ); + final container = tester.widget(find.byType(Container).first); + expect((container.decoration as BoxDecoration).color, equals(Colors.pink)); + }); +} diff --git a/example/widgetbook/components/status_label_widgetbook.dart b/example/widgetbook/components/status_label_widgetbook.dart index 6ddaeaf9..6b5e61c3 100644 --- a/example/widgetbook/components/status_label_widgetbook.dart +++ b/example/widgetbook/components/status_label_widgetbook.dart @@ -19,7 +19,7 @@ WidgetbookComponent statusLabelWidgetBook() { statusLabelExampleRow(WidgetSeverity.negative), statusLabelExampleRow( WidgetSeverity.custom, - colors: ZetaStatusLabelColors(accentColor: Colors.blue, backgroundColor: Colors.blue.shade50), + colors: ZetaWidgetColor(foregroundColor: Colors.blue, backgroundColor: Colors.blue.shade50), ), ], ), diff --git a/example/widgetbook/components/workcloud_indicator_widgetbook.dart b/example/widgetbook/components/workcloud_indicator_widgetbook.dart new file mode 100644 index 00000000..fbf000b4 --- /dev/null +++ b/example/widgetbook/components/workcloud_indicator_widgetbook.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/workcloud_indicator_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent workcloudIndicatorWidgetBook() { + return WidgetbookComponent( + name: 'Workcloud Indicator', + useCases: [ + WidgetbookUseCase( + name: 'Status', + builder: (context) => SingleChildScrollView( + child: Column( + children: [ + Row(children: [ + Padding( + padding: EdgeInsets.all(10), + child: ZetaWorkcloudIndicator.status(label: 'Status'), + ) + ]), + Row(children: [ + Padding( + padding: EdgeInsets.all(10), + child: ZetaWorkcloudIndicator.status(label: 'In Progress'), + ) + ]), + Row(children: [ + Padding( + padding: EdgeInsets.all(10), + child: ZetaWorkcloudIndicator.status(label: 'Reviewed'), + ) + ]), + Row(children: [ + Padding( + padding: EdgeInsets.all(10), + child: ZetaWorkcloudIndicator.status(label: 'Resolved'), + ) + ]), + ], + ), + ), + ), + WidgetbookUseCase( + name: 'Priority Pill', + builder: (context) => SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: EdgeInsets.all(10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [Text('Medium'), Text('Small'), Text('X-Small')], + ), + ), + workcloudIndicatorExampleRow('Urgent', 'U', ZetaWorkcloudIndicatorType.urgent), + workcloudIndicatorExampleRow('High', '1', ZetaWorkcloudIndicatorType.high), + workcloudIndicatorExampleRow('Medium', '2', ZetaWorkcloudIndicatorType.medium), + workcloudIndicatorExampleRow('Low', '3', ZetaWorkcloudIndicatorType.low), + workcloudIndicatorExampleRow('Custom', '4', ZetaWorkcloudIndicatorType.custom, + colors: + ZetaWidgetColor(backgroundColor: Colors.purple, foregroundColor: Colors.purple.shade50)), + ], + ), + )) + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 67b82828..afd3d11b 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -12,6 +12,7 @@ import 'components/priority_pill_widgetbook.dart'; import 'components/spacing_widgetbook.dart'; import 'components/status_label_widgetbook.dart'; import 'components/typography_widgetbook.dart'; +import 'components/workcloud_indicator_widgetbook.dart'; import 'utils/zebra.dart'; class HotReload extends StatelessWidget { @@ -34,6 +35,7 @@ class HotReload extends StatelessWidget { badgeWidgetBook(), indicatorWidgetBook(), priorityPillWidgetBook(), + workcloudIndicatorWidgetBook(), avatarWidgetBook(), checkboxWidgetBook() ], diff --git a/lib/src/components/status_label.dart b/lib/src/components/status_label.dart index 629aa351..3172ffa7 100644 --- a/lib/src/components/status_label.dart +++ b/lib/src/components/status_label.dart @@ -2,21 +2,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../zeta_flutter.dart'; -///Zeta Status Label Colors -class ZetaStatusLabelColors { - ///Constructs [ZetaStatusLabelColors]. - const ZetaStatusLabelColors({ - required this.backgroundColor, - required this.accentColor, - }); - - ///Background Color - final Color backgroundColor; - - ///Border and Icon Color - final Color accentColor; -} - ///Zeta Status Label class ZetaStatusLabel extends StatelessWidget { ///Constructs [ZetaStatusLabel]. @@ -55,7 +40,7 @@ class ZetaStatusLabel extends StatelessWidget { final String label; ///Colors for the label - final ZetaStatusLabelColors? customColors; + final ZetaWidgetColor? customColors; ///Whether the icon is the default icon /// @@ -82,15 +67,15 @@ class ZetaStatusLabel extends StatelessWidget { ); } - BoxDecoration _buildDecoration(ZetaStatusLabelColors colors) { + BoxDecoration _buildDecoration(ZetaWidgetColor colors) { return BoxDecoration( color: colors.backgroundColor, - border: Border.all(color: colors.accentColor, width: borderWidth), + border: Border.all(color: colors.foregroundColor, width: borderWidth), borderRadius: BorderRadius.circular(borderType == BorderType.rounded ? 10.0 : 0.0), ); } - Widget _buildContent(ZetaStatusLabelColors colors, Zeta theme) { + Widget _buildContent(ZetaWidgetColor colors, Zeta theme) { return Padding( padding: const EdgeInsets.fromLTRB(8, 2, 8, 2), child: Row( @@ -110,42 +95,42 @@ class ZetaStatusLabel extends StatelessWidget { ); } - Icon _buildIcon(ZetaStatusLabelColors colors) { + Icon _buildIcon(ZetaWidgetColor colors) { final size = isDefaultIcon ? Dimensions.x2 : customIconSize; return Icon( size: size, isDefaultIcon ? Icons.circle : (customIcon ?? Icons.star), - color: colors.accentColor, + color: colors.foregroundColor, ); } - ZetaStatusLabelColors _getColors(Zeta theme) { - final defaultColorScheme = ZetaStatusLabelColors( + ZetaWidgetColor _getColors(Zeta theme) { + final defaultColorScheme = ZetaWidgetColor( backgroundColor: theme.colors.surfaceDisabled, - accentColor: theme.colors.borderDefault, + foregroundColor: theme.colors.borderDefault, ); switch (severity) { case WidgetSeverity.neutral: return defaultColorScheme; case WidgetSeverity.info: - return ZetaStatusLabelColors( + return ZetaWidgetColor( backgroundColor: theme.colors.purple.shade10, - accentColor: theme.colors.purple.shade50, + foregroundColor: theme.colors.purple.shade50, ); case WidgetSeverity.positive: - return ZetaStatusLabelColors( + return ZetaWidgetColor( backgroundColor: theme.colors.green.shade10, - accentColor: theme.colors.green.shade50, + foregroundColor: theme.colors.green.shade50, ); case WidgetSeverity.warning: - return ZetaStatusLabelColors( + return ZetaWidgetColor( backgroundColor: theme.colors.orange.shade10, - accentColor: theme.colors.orange.shade50, + foregroundColor: theme.colors.orange.shade50, ); case WidgetSeverity.negative: - return ZetaStatusLabelColors( + return ZetaWidgetColor( backgroundColor: theme.colors.red.shade10, - accentColor: theme.colors.red.shade50, + foregroundColor: theme.colors.red.shade50, ); case WidgetSeverity.custom: return customColors ?? defaultColorScheme; @@ -162,7 +147,7 @@ class ZetaStatusLabel extends StatelessWidget { ..add(EnumProperty('severity', severity)) ..add(StringProperty('label', label)) ..add( - DiagnosticsProperty( + DiagnosticsProperty( 'customColors', customColors, ), diff --git a/lib/src/components/workcloud_indicator.dart b/lib/src/components/workcloud_indicator.dart new file mode 100644 index 00000000..2d9b81b6 --- /dev/null +++ b/lib/src/components/workcloud_indicator.dart @@ -0,0 +1,275 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; + +///Indicator Type +enum ZetaWorkcloudIndicatorType { + ///sets the color to red + urgent, + + ///sets the color to orange + high, + + ///sets the color to blue + medium, + + ///sets the color to green + low, + + ///sets the color to custom color + custom +} + +///Zeta Workcloud Indicator +class ZetaWorkcloudIndicator extends StatelessWidget { + ///Constructs [ZetaWorkcloudIndicator] + const ZetaWorkcloudIndicator({ + this.isStatusBadge = true, + this.priorityType, + this.prioritySize = ZetaWidgetSize.small, + this.label, + this.index, + this.customColors, + super.key, + }); + + ///Constructor for [ZetaWorkcloudIndicator] for type 'status' + factory ZetaWorkcloudIndicator.status({ + required String label, + }) => + ZetaWorkcloudIndicator(label: label); + + ///Constructor for [ZetaWorkcloudIndicator] for type 'priority pill' + factory ZetaWorkcloudIndicator.priorityPill({ + required String index, + ZetaWorkcloudIndicatorType priorityType = ZetaWorkcloudIndicatorType.urgent, + ZetaWidgetSize prioritySize = ZetaWidgetSize.small, + ZetaWidgetColor? customColors, + String? label, + }) => + ZetaWorkcloudIndicator( + isStatusBadge: false, + priorityType: priorityType, + prioritySize: prioritySize, + label: label, + index: index, + customColors: customColors, + ); + + ///Indicates if it is status badge or priority pill + /// + /// Defaults to status + final bool isStatusBadge; + + ///The type of priority for Priority Pill + /// + ///[ZetaWorkcloudIndicator.priorityPill] defaults to 'urgent' + final ZetaWorkcloudIndicatorType? priorityType; + + ///The size of Priority Pill + /// + ///defaults to 'small' + final ZetaWidgetSize prioritySize; + + ///Label + final String? label; + + ///Index for priority pill + /// + ///required for [ZetaWorkcloudIndicator.priorityPill] + final String? index; + + ///Custom colors for priority pill + final ZetaWidgetColor? customColors; + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + final themeMode = Zeta.of(context).themeMode; + return isStatusBadge ? _buildStatusBadge(theme) : _buildPriorityPill(theme, themeMode); + } + + ///Status Badge + Widget _buildStatusBadge(Zeta theme) { + final labelContent = label ?? ''; + return Container( + height: Dimensions.x6, + constraints: const BoxConstraints(minWidth: 51), + decoration: _statusBadgeDecoration(theme), + child: Center( + child: Padding( + padding: const EdgeInsets.fromLTRB( + Dimensions.x2, + Dimensions.x1, + Dimensions.x2, + Dimensions.x1, + ), + child: Text(labelContent, style: ZetaText.zetaBodyXSmall), + ), + ), + ); + } + + BoxDecoration _statusBadgeDecoration(Zeta theme) { + return BoxDecoration( + color: theme.colors.surfaceDisabled, + borderRadius: BorderRadius.circular(6), + ); + } + + ///Priority Pill + Widget _buildPriorityPill(Zeta theme, ThemeMode themeMode) { + final colors = _ZetaWorkcloudIndicatorStyle.getColor( + priorityType ?? ZetaWorkcloudIndicatorType.urgent, + theme.colors, + themeMode, + customColors: customColors, + ); + final size = _ZetaWorkcloudIndicatorStyle.getSize(prioritySize); + final padding = _ZetaWorkcloudIndicatorStyle.getEdgeInsets(prioritySize); + final textStyle = _ZetaWorkcloudIndicatorStyle.getTextStyle(prioritySize, theme); + + return DecoratedBox( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(Dimensions.l), + color: colors.foregroundColor, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + _buildPriorityPillIndex(size, colors, textStyle, theme), + if (prioritySize != ZetaWidgetSize.small) ...[ + _buildPriorityPillLabel(size, textStyle, padding), + ], + ], + ), + ); + } + + Widget _buildPriorityPillIndex( + double size, + ZetaWidgetColor colors, + TextStyle textStyle, + Zeta theme, + ) { + return Container( + alignment: Alignment.center, + height: size, + width: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: colors.backgroundColor, + ), + child: Center( + child: Text( + index ?? '', + style: textStyle.apply(color: theme.colors.white), + textAlign: TextAlign.center, + ), + ), + ); + } + + Widget _buildPriorityPillLabel( + double size, + TextStyle textStyle, + EdgeInsets padding, + ) { + return Container( + height: size, + constraints: const BoxConstraints(minWidth: 34), + child: Padding( + padding: padding, + child: Text( + label ?? '', + style: textStyle, + overflow: TextOverflow.ellipsis, + ), + ), + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('isStatusBadge', isStatusBadge)) + ..add( + EnumProperty('priorityType', priorityType), + ) + ..add( + EnumProperty('prioritySize', prioritySize), + ) + ..add(StringProperty('label', label)) + ..add(StringProperty('index', index)) + ..add( + DiagnosticsProperty('customColors', customColors), + ); + } +} + +class _ZetaIndicatorConstants { + static const double mediumSize = 22; + static const double largeSize = 24; + static const EdgeInsets largePadding = EdgeInsets.fromLTRB(8, 0, 8, 1); + static const EdgeInsets mediumPadding = EdgeInsets.fromLTRB(8, 2, 8, 2); +} + +class _ZetaWorkcloudIndicatorStyle { + static ZetaWidgetColor getColor( + ZetaWorkcloudIndicatorType type, + ZetaColors zetaColors, + ThemeMode themeMode, { + ZetaWidgetColor? customColors, + }) { + final isDarkTheme = themeMode == ThemeMode.dark; + switch (type) { + case ZetaWorkcloudIndicatorType.urgent: + return ZetaWidgetColor( + backgroundColor: isDarkTheme ? ZetaColorBase.red.shade70 : ZetaColorBase.red.shade60, + foregroundColor: isDarkTheme ? ZetaColorBase.red.shade90 : ZetaColorBase.red.shade20, + ); + case ZetaWorkcloudIndicatorType.high: + return ZetaWidgetColor( + backgroundColor: isDarkTheme ? ZetaColorBase.orange.shade70 : ZetaColorBase.orange.shade40, + foregroundColor: isDarkTheme ? ZetaColorBase.orange.shade90 : ZetaColorBase.orange.shade10, + ); + case ZetaWorkcloudIndicatorType.medium: + return ZetaWidgetColor( + backgroundColor: isDarkTheme ? ZetaColorBase.blue.shade70 : ZetaColorBase.blue, + foregroundColor: isDarkTheme ? ZetaColorBase.blue.shade90 : ZetaColorBase.blue.shade20, + ); + case ZetaWorkcloudIndicatorType.low: + return ZetaWidgetColor( + backgroundColor: isDarkTheme ? ZetaColorBase.green.shade70 : ZetaColorBase.green.shade60, + foregroundColor: isDarkTheme ? ZetaColorBase.green.shade90 : ZetaColorBase.green.shade20, + ); + case ZetaWorkcloudIndicatorType.custom: + return customColors ?? + ZetaWidgetColor( + backgroundColor: zetaColors.surfaceDisabled, + foregroundColor: zetaColors.surfacePrimary, + ); + } + } + + static double getSize(ZetaWidgetSize size) { + if (size == ZetaWidgetSize.large) { + return _ZetaIndicatorConstants.largeSize; + } + return _ZetaIndicatorConstants.mediumSize; + } + + static TextStyle getTextStyle(ZetaWidgetSize size, Zeta theme) { + if (size == ZetaWidgetSize.large) return ZetaText.zetaBodyMedium; + return ZetaText.zetaBodySmall; + } + + static EdgeInsets getEdgeInsets(ZetaWidgetSize size) { + if (size == ZetaWidgetSize.large) { + return _ZetaIndicatorConstants.largePadding; + } + return _ZetaIndicatorConstants.mediumPadding; + } +} diff --git a/lib/src/utils/enums.dart b/lib/src/utils/enums.dart index 9760794b..c4ace7b2 100644 --- a/lib/src/utils/enums.dart +++ b/lib/src/utils/enums.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + ///Border Types enum BorderType { ///sharp border @@ -27,3 +29,30 @@ enum WidgetSeverity { ///Custom Label custom } + +///Widget Colors +class ZetaWidgetColor { + ///Constructs [ZetaWidgetColor]. + const ZetaWidgetColor({ + required this.backgroundColor, + required this.foregroundColor, + }); + + ///Background Color + final Color backgroundColor; + + ///foregroundColor Color + final Color foregroundColor; +} + +///Zeta Widget Size +enum ZetaWidgetSize { + /// [large] + large, + + /// [medium] + medium, + + /// [small] + small, +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index dd4bfc6e..32db711e 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -11,6 +11,7 @@ export 'src/components/spacing.dart'; export 'src/components/status_label.dart'; export 'src/components/system_banner.dart'; export 'src/components/text.dart'; +export 'src/components/workcloud_indicator.dart'; export 'src/icons.dart'; export 'src/theme/color_extensions.dart'; export 'src/theme/color_scheme.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index e8668658..ed10b14c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+4 +version: 0.1.1+5 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. From ac2b269c5806d2af310a063231abc1e412aea1a1 Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Mon, 18 Dec 2023 14:45:43 +0200 Subject: [PATCH 15/41] fix the border of the indicator component (#31) * fix the border of the component * [automated commit] lint format and import sort * inverseBorder * [automated commit] lint format and import sort * rounded = true by default * running on iPhone * try to adjust font height * horizontal alignment * try to remove the line height * stick to Material 2 for now --------- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions --- CHANGELOG.md | 106 ++++++++++++++++++----- example/ios/Podfile.lock | 9 +- example/lib/main.dart | 1 + example/lib/pages/indicator_example.dart | 62 ++++++++++++- lib/src/components/indicator.dart | 94 ++++++++++++-------- pubspec.yaml | 2 +- 6 files changed, 209 insertions(+), 65 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43c8c79a..c96a3af1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,49 +1,108 @@ -## [0.1.1+5] - 2023-12-18 +## [0.1.1+6] - 2023-12-18 ### :flying_saucer: Other Changes -- [`1268c92`](https://github.com/zebratechnologies/zeta-flutter/commit/1268c92c7e0057cd166c40bc9ccd53ccf80c2fef) - App bar ([#35](https://github.com/zebratechnologies/zeta-flutter/pull/35)) +- [`354040c`](https://github.com/zebratechnologies/zeta-flutter/commit/354040c91731f53f9186ce0cbce341706dc30b3a) - Workcloud indicators ([#34](https://github.com/zebratechnologies/zeta-flutter/pull/34)) -* create ZetaAppBar in four variants with example screens +* initial + +* workcloud indicator + +* typo + +* . * [automated commit] lint format and import sort -* remove Flexible +* . -* rename +* . -* titleIcon should be of type Icon instead of Widget +* . + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* add default values + +* [automated commit] lint format and import sort --------- -Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* -- [`077d161`](https://github.com/zebratechnologies/zeta-flutter/commit/077d16138d5d3f579fbc2bfcba3048b1c5d28afc) - Workcloud indicators ([#34](https://github.com/zebratechnologies/zeta-flutter/pull/34)) +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`88080ad`](https://github.com/zebratechnologies/zeta-flutter/commit/88080ada71811b47fe20f73dfba23c52e5223d38) - fix the border of the indicator component ([#31](https://github.com/zebratechnologies/zeta-flutter/pull/31)) -* initial +* fix the border of the component -* workcloud indicator - -* typo +* [automated commit] lint format and import sort -* . +* inverseBorder * [automated commit] lint format and import sort -* . +* rounded = true by default -* . +* running on iPhone -* . +* try to adjust font height -* [automated commit] lint format and import sort +* horizontal alignment -* [automated commit] lint format and import sort +* try to remove the line height -* add default values - -* [automated commit] lint format and import sort +* stick to Material 2 for now --------- +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + +## [0.1.1+5] - 2023-12-18 +### :flying_saucer: Other Changes +- [`1268c92`](https://github.com/zebratechnologies/zeta-flutter/commit/1268c92c7e0057cd166c40bc9ccd53ccf80c2fef) - App bar ([#35](https://github.com/zebratechnologies/zeta-flutter/pull/35)) + +* create ZetaAppBar in four variants with example screens + +* [automated commit] lint format and import sort + +* remove Flexible + +* rename + +* titleIcon should be of type Icon instead of Widget + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`077d161`](https://github.com/zebratechnologies/zeta-flutter/commit/077d16138d5d3f579fbc2bfcba3048b1c5d28afc) - Workcloud indicators ([#34](https://github.com/zebratechnologies/zeta-flutter/pull/34)) + +* initial + +* workcloud indicator + +* typo + +* . + +* [automated commit] lint format and import sort + +* . + +* . + +* . + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* add default values + +* [automated commit] lint format and import sort + +--------- + Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* @@ -759,4 +818,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+2]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.0+9...0.1.1+2 [0.1.1+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+2...0.1.1+3 [0.1.1+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+3...0.1.1+4 -[0.1.1+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+4...0.1.1+5 \ No newline at end of file +[0.1.1+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+4...0.1.1+5 +[0.1.1+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+5...0.1.1+6 \ No newline at end of file diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index f5c285f1..f6342e74 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -3,21 +3,28 @@ PODS: - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS DEPENDENCIES: - Flutter (from `Flutter`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) EXTERNAL SOURCES: Flutter: :path: Flutter path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" SPEC CHECKSUMS: Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.13.0 +COCOAPODS: 1.14.3 diff --git a/example/lib/main.dart b/example/lib/main.dart index 5249b291..75e344b5 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -49,6 +49,7 @@ class ZetaExample extends StatelessWidget { routerConfig: router, themeMode: themeMode, theme: ThemeData( + useMaterial3: false, fontFamily: themeData.fontFamily, scaffoldBackgroundColor: light.background, colorScheme: light, diff --git a/example/lib/pages/indicator_example.dart b/example/lib/pages/indicator_example.dart index 2cd13726..6a4313ab 100644 --- a/example/lib/pages/indicator_example.dart +++ b/example/lib/pages/indicator_example.dart @@ -59,6 +59,22 @@ class IndicatorExample extends StatelessWidget { ), ], ), + const SizedBox(height: 8), + Row( + children: [ + ZetaIndicator.icon(inverseBorder: true), + const SizedBox(width: 20), + ZetaIndicator.icon( + size: ZetaIndicatorSize.medium, + inverseBorder: true, + ), + const SizedBox(width: 20), + ZetaIndicator.icon( + size: ZetaIndicatorSize.small, + inverseBorder: true, + ), + ], + ), ], ), const SizedBox(width: 50), @@ -72,11 +88,11 @@ class IndicatorExample extends StatelessWidget { const SizedBox(height: 8), Row( children: [ - ZetaIndicator.icon(sharp: true), + ZetaIndicator.icon(rounded: false), const SizedBox(width: 20), ZetaIndicator.icon( size: ZetaIndicatorSize.medium, - sharp: true, + rounded: false, ), const SizedBox(width: 20), ZetaIndicator.icon( @@ -84,6 +100,26 @@ class IndicatorExample extends StatelessWidget { ), ], ), + const SizedBox(height: 8), + Row( + children: [ + ZetaIndicator.icon( + rounded: false, + inverseBorder: true, + ), + const SizedBox(width: 20), + ZetaIndicator.icon( + size: ZetaIndicatorSize.medium, + rounded: false, + inverseBorder: true, + ), + const SizedBox(width: 20), + ZetaIndicator.icon( + size: ZetaIndicatorSize.small, + inverseBorder: true, + ), + ], + ), ], ), ], @@ -97,7 +133,7 @@ class IndicatorExample extends StatelessWidget { 'ZetaIndicator.notification', style: TextStyle(fontWeight: FontWeight.bold), ), - const SizedBox(height: 15), + const SizedBox(height: 8), Row( children: [ ZetaIndicator.notification( @@ -115,6 +151,26 @@ class IndicatorExample extends StatelessWidget { ), ], ), + const SizedBox(height: 8), + Row( + children: [ + ZetaIndicator.notification( + value: 3, + inverseBorder: true, + ), + const SizedBox(width: 20), + ZetaIndicator.notification( + size: ZetaIndicatorSize.medium, + value: 3, + inverseBorder: true, + ), + const SizedBox(width: 20), + ZetaIndicator.notification( + size: ZetaIndicatorSize.small, + inverseBorder: true, + ), + ], + ), ], ); } diff --git a/lib/src/components/indicator.dart b/lib/src/components/indicator.dart index fc0df803..caae698f 100644 --- a/lib/src/components/indicator.dart +++ b/lib/src/components/indicator.dart @@ -31,11 +31,12 @@ class ZetaIndicator extends StatelessWidget { required this.type, this.size = ZetaIndicatorSize.large, this.icon, - this.sharp = false, + this.rounded = true, this.value, this.backgroundColor, this.foregroundColor, this.borderColor, + this.inverseBorder = false, }) { _sizePixels = getSizePixels(size, type); } @@ -46,8 +47,9 @@ class ZetaIndicator extends StatelessWidget { Color? backgroundColor, Color? foregroundColor, Color? borderColor, + bool inverseBorder = false, Icon? icon, - bool sharp = false, + bool rounded = true, }) => ZetaIndicator( type: ZetaIndicatorType.icon, @@ -55,8 +57,9 @@ class ZetaIndicator extends StatelessWidget { backgroundColor: backgroundColor, foregroundColor: foregroundColor, borderColor: borderColor, + inverseBorder: inverseBorder, icon: icon, - sharp: sharp, + rounded: rounded, ); /// Constructor for [ZetaIndicator] of type `icon` @@ -65,6 +68,7 @@ class ZetaIndicator extends StatelessWidget { Color? backgroundColor, Color? foregroundColor, Color? borderColor, + bool inverseBorder = false, int? value, }) => ZetaIndicator( @@ -73,31 +77,40 @@ class ZetaIndicator extends StatelessWidget { backgroundColor: backgroundColor, foregroundColor: foregroundColor, borderColor: borderColor, + inverseBorder: inverseBorder, value: value, ); /// The type of the [ZetaIndicator] - icon or notification final ZetaIndicatorType type; - /// The size of the [ZetaIndicator] + /// The size of the [ZetaIndicator]. Default is [ZetaIndicatorSize.large] final ZetaIndicatorSize size; - /// Background color + /// Background color. + /// Default is blue for [ZetaIndicatorType.icon] + /// and negative for [ZetaIndicatorType.notification]. final Color? backgroundColor; - /// Foreground color + /// Foreground color. Default is white. final Color? foregroundColor; - /// Border color + /// Border color. + /// Default is surfacePrimary or textDefault + /// depending on theme mode (light or dark) and [inverseBorder]. final Color? borderColor; + /// Inverse the border color. Not considered, if [borderColor] is provided. + final bool inverseBorder; + /// Indicator icon, default: `ZetaIcons.star_round` final Icon? icon; - /// Determines if the default icon should be sharp: `ZetaIcons.star_sharp`. - /// Default is `false`. + /// Determines if the default icon should be rounded or sharp: + /// `ZetaIcons.star_round` or `ZetaIcons.star_sharp`. + /// Default is `true`. /// Not taken into account, if [icon] is provided. - final bool sharp; + final bool rounded; /// Value for the type `notification` final int? value; @@ -112,27 +125,33 @@ class ZetaIndicator extends StatelessWidget { width: _sizePixels + 4, height: _sizePixels + 4, decoration: BoxDecoration( - color: backgroundColor ?? (type == ZetaIndicatorType.icon ? zetaColors.blue : zetaColors.negative), - border: Border.all( - color: borderColor ?? zetaColors.surfacePrimary, - width: 2, - ), + color: borderColor ?? (inverseBorder ? zetaColors.textDefault : zetaColors.surfacePrimary), borderRadius: BorderRadius.circular(20), ), - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - clipBehavior: Clip.hardEdge, - child: size == ZetaIndicatorSize.small - ? null - : _InnerContent( - type: type, - size: size, - sizePixels: _sizePixels, - icon: icon, - sharp: sharp, - value: value, - foregroundColor: foregroundColor, - ), + child: Center( + child: Container( + width: _sizePixels, + height: _sizePixels, + decoration: BoxDecoration( + color: backgroundColor ?? (type == ZetaIndicatorType.icon ? zetaColors.blue : zetaColors.negative), + borderRadius: BorderRadius.circular(16), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + clipBehavior: Clip.hardEdge, + child: size == ZetaIndicatorSize.small + ? null + : _InnerContent( + type: type, + size: size, + sizePixels: _sizePixels, + icon: icon, + rounded: rounded, + value: value, + foregroundColor: foregroundColor, + ), + ), + ), ), ); } @@ -157,10 +176,11 @@ class ZetaIndicator extends StatelessWidget { ..add(DiagnosticsProperty('size', size)) ..add(DiagnosticsProperty('value', value)) ..add(DiagnosticsProperty('icon', icon)) - ..add(DiagnosticsProperty('sharp', sharp)) + ..add(DiagnosticsProperty('rounded', rounded)) ..add(DiagnosticsProperty('backgroundColor', backgroundColor)) ..add(DiagnosticsProperty('foregroundColor', foregroundColor)) - ..add(DiagnosticsProperty('borderColor', borderColor)); + ..add(DiagnosticsProperty('borderColor', borderColor)) + ..add(DiagnosticsProperty('inverseBorder', inverseBorder)); } } @@ -170,7 +190,7 @@ class _InnerContent extends StatelessWidget { required this.size, required this.sizePixels, this.icon, - this.sharp = false, + this.rounded = true, this.value, this.foregroundColor, }); @@ -179,7 +199,7 @@ class _InnerContent extends StatelessWidget { final ZetaIndicatorSize size; final double sizePixels; final Icon? icon; - final bool sharp; + final bool rounded; final int? value; final Color? foregroundColor; @@ -195,7 +215,7 @@ class _InnerContent extends StatelessWidget { color: foregroundColor ?? defaultColor, size: iconSize, ), - child: icon ?? Icon(sharp ? ZetaIcons.star_sharp : ZetaIcons.star_round), + child: icon ?? Icon(rounded ? ZetaIcons.star_round : ZetaIcons.star_sharp), ), ); case ZetaIndicatorType.notification: @@ -204,10 +224,10 @@ class _InnerContent extends StatelessWidget { return Center( child: Text( strVal.length > 1 ? '9+' : strVal, - textAlign: strVal.length == 1 ? null : TextAlign.right, + textAlign: strVal.length == 1 ? TextAlign.center : TextAlign.right, style: TextStyle( fontSize: fontSize, - height: fontSize * .067, + // height: .9, letterSpacing: -0.5, color: foregroundColor ?? defaultColor, ), @@ -247,7 +267,7 @@ class _InnerContent extends StatelessWidget { ..add(DiagnosticsProperty('sizePixels', sizePixels)) ..add(DiagnosticsProperty('value', value)) ..add(DiagnosticsProperty('icon', icon)) - ..add(DiagnosticsProperty('sharp', sharp)) + ..add(DiagnosticsProperty('rounded', rounded)) ..add(DiagnosticsProperty('foregroundColor', foregroundColor)); } } diff --git a/pubspec.yaml b/pubspec.yaml index ed10b14c..fbac203a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+5 +version: 0.1.1+6 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. From 4ca71f3f83535e55c3af36961a5332fced0ecdbf Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Mon, 18 Dec 2023 16:20:20 +0200 Subject: [PATCH 16/41] Button component (#36) * initial * format_error * [automated commit] lint format and import sort * button component optimizations * [automated commit] lint format and import sort * [automated commit] lint format and import sort * colors change * colors change * [automated commit] lint format and import sort --------- Co-authored-by: github-actions --- CHANGELOG.md | 102 ++++++-- example/lib/home.dart | 2 + example/lib/pages/button_example.dart | 200 +++++++++++++++ example/pubspec.lock | 2 +- example/test/button_test.dart | 40 +++ .../components/button_widgetbook.dart | 26 ++ example/widgetbook/widgetbook.dart | 4 +- lib/src/components/button.dart | 241 ++++++++++++++++++ lib/src/utils/enums.dart | 24 +- lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 11 files changed, 605 insertions(+), 39 deletions(-) create mode 100644 example/lib/pages/button_example.dart create mode 100644 example/test/button_test.dart create mode 100644 example/widgetbook/components/button_widgetbook.dart create mode 100644 lib/src/components/button.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index c96a3af1..970ade36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,56 @@ +## [0.1.1+7] - 2023-12-18 +### :flying_saucer: Other Changes +- [`ac2b269`](https://github.com/zebratechnologies/zeta-flutter/commit/ac2b269c5806d2af310a063231abc1e412aea1a1) - fix the border of the indicator component ([#31](https://github.com/zebratechnologies/zeta-flutter/pull/31)) + +* fix the border of the component + +* [automated commit] lint format and import sort + +* inverseBorder + +* [automated commit] lint format and import sort + +* rounded = true by default + +* running on iPhone + +* try to adjust font height + +* horizontal alignment + +* try to remove the line height + +* stick to Material 2 for now + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`cb330c7`](https://github.com/zebratechnologies/zeta-flutter/commit/cb330c7c1952ca2493b5d6c9272e2ade1050f53b) - Button component ([#36](https://github.com/zebratechnologies/zeta-flutter/pull/36)) + +* initial + +* format_error + +* [automated commit] lint format and import sort + +* button component optimizations + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* colors change + +* colors change + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + ## [0.1.1+6] - 2023-12-18 ### :flying_saucer: Other Changes - [`354040c`](https://github.com/zebratechnologies/zeta-flutter/commit/354040c91731f53f9186ce0cbce341706dc30b3a) - Workcloud indicators ([#34](https://github.com/zebratechnologies/zeta-flutter/pull/34)) @@ -31,29 +84,29 @@ Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`88080ad`](https://github.com/zebratechnologies/zeta-flutter/commit/88080ada71811b47fe20f73dfba23c52e5223d38) - fix the border of the indicator component ([#31](https://github.com/zebratechnologies/zeta-flutter/pull/31)) -* fix the border of the component - -* [automated commit] lint format and import sort - -* inverseBorder - -* [automated commit] lint format and import sort - -* rounded = true by default - -* running on iPhone - -* try to adjust font height - -* horizontal alignment - -* try to remove the line height - -* stick to Material 2 for now - ---------- - -Co-authored-by: Atanas Yordanov +* fix the border of the component + +* [automated commit] lint format and import sort + +* inverseBorder + +* [automated commit] lint format and import sort + +* rounded = true by default + +* running on iPhone + +* try to adjust font height + +* horizontal alignment + +* try to remove the line height + +* stick to Material 2 for now + +--------- + +Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -819,4 +872,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+3]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+2...0.1.1+3 [0.1.1+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+3...0.1.1+4 [0.1.1+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+4...0.1.1+5 -[0.1.1+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+5...0.1.1+6 \ No newline at end of file +[0.1.1+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+5...0.1.1+6 +[0.1.1+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+6...0.1.1+7 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 3d1eeba6..d4487a0f 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -7,6 +7,7 @@ import 'package:zeta_example/pages/app_bar_example/positive_app_bar.dart'; import 'package:zeta_example/pages/app_bar_example/warning_app_bar.dart'; import 'package:zeta_example/pages/avatar_example.dart'; import 'package:zeta_example/pages/badge_example.dart'; +import 'package:zeta_example/pages/button_example.dart'; import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/checkbox_example.dart'; import 'package:zeta_example/pages/grid_example.dart'; @@ -47,6 +48,7 @@ final List components = [ Component(NegativeAppBarExample.name, (context) => const NegativeAppBarExample()), ]), Component(CheckBoxExample.name, (context) => const CheckBoxExample()), + Component(ButtonExample.name, (context) => const ButtonExample()), ]; class Home extends StatefulWidget { diff --git a/example/lib/pages/button_example.dart b/example/lib/pages/button_example.dart new file mode 100644 index 00000000..1e8baead --- /dev/null +++ b/example/lib/pages/button_example.dart @@ -0,0 +1,200 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class ButtonExample extends StatelessWidget { + static const String name = 'Button'; + + const ButtonExample({super.key}); + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + final colors = BuildExampleButtonColors(theme: theme); + + return ExampleScaffold( + name: 'Button', + child: Padding( + padding: EdgeInsets.all(10), + child: SingleChildScrollView( + child: Column( + children: [roundedButtonsExample(colors), Divider(), Divider(), sharpButtonsExample(colors)], + ), + ), + ), + ); + } +} + +Widget roundedButtonsExample(BuildExampleButtonColors colors) => Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ..._getZetaButtonExampleRows('Primary', colors.primaryColors), + Divider(), + ..._getZetaButtonExampleRows('Primary Variant', colors.primaryVariantColors), + Divider(), + ..._getZetaButtonExampleRows('Negative', colors.negativeColors, icon: ZetaIcons.delete_round), + Divider(), + ..._getZetaButtonExampleRows('Outlined', colors.outlined, buttonType: ZetaButtonType.outlined), + Divider(), + ..._getZetaButtonExampleRows('Outlined Subtle', colors.outlinedSubtle, buttonType: ZetaButtonType.outlined), + Divider(), + ..._getZetaButtonExampleRows('Text', colors.textColors), + Divider(), + ..._getZetaButtonExampleRows('Text Inverse', colors.textInverseColor), + ], + ); + +Widget sharpButtonsExample(BuildExampleButtonColors colors) => Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ..._getZetaButtonExampleRows('Primary', colors.primaryColors, border: BorderType.sharp), + Divider(), + ..._getZetaButtonExampleRows('Primary Variant', colors.primaryVariantColors, border: BorderType.sharp), + Divider(), + ..._getZetaButtonExampleRows('Negative', colors.negativeColors, + icon: ZetaIcons.delete_sharp, border: BorderType.sharp), + Divider(), + ..._getZetaButtonExampleRows('Outlined', colors.outlined, + buttonType: ZetaButtonType.outlined, border: BorderType.sharp), + Divider(), + ..._getZetaButtonExampleRows('Outlined Subtle', colors.outlinedSubtle, + buttonType: ZetaButtonType.outlined, border: BorderType.sharp), + Divider(), + ..._getZetaButtonExampleRows('Text', colors.textColors, border: BorderType.sharp), + Divider(), + ..._getZetaButtonExampleRows('Text Inverse', colors.textInverseColor, border: BorderType.sharp), + ], + ); + +List _getZetaButtonExampleRows(String label, ZetaButtonColors colors, + {IconData? icon, ZetaButtonType buttonType = ZetaButtonType.filled, BorderType border = BorderType.rounded}) { + return [ + Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text('Large $label', style: ZetaText.zetaTitleLarge)]), + Divider(color: Colors.transparent), + _getRow(buttonType, ZetaWidgetSize.large, colors, border: border, icon: icon), + Divider(color: Colors.transparent), + _getRow(buttonType, ZetaWidgetSize.large, colors, isDisabled: true, border: border, icon: icon), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [Padding(padding: EdgeInsets.all(10), child: Text('Medium $label', style: ZetaText.zetaTitleLarge))], + ), + _getRow(buttonType, ZetaWidgetSize.medium, colors, border: border, icon: icon), + _getRow(buttonType, ZetaWidgetSize.medium, colors, isDisabled: true, border: border, icon: icon), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [Padding(padding: EdgeInsets.all(10), child: Text('Small $label', style: ZetaText.zetaTitleLarge))], + ), + _getRow(buttonType, ZetaWidgetSize.small, colors, border: border, icon: icon), + _getRow(buttonType, ZetaWidgetSize.small, colors, isDisabled: true, border: border, icon: icon), + ]; +} + +Widget _getRow(ZetaButtonType type, ZetaWidgetSize size, ZetaButtonColors colors, + {bool isDisabled = false, IconData? icon, BorderType border = BorderType.rounded}) { + final IconData defaultIcon = border == BorderType.rounded ? ZetaIcons.star_round : ZetaIcons.star_sharp; + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _getZetaButtonExample(type, size, colors, isDisabled: isDisabled, border: border), + _getZetaButtonExample(type, size, colors, icon: icon ?? defaultIcon, isDisabled: isDisabled, border: border), + _getZetaButtonExample(type, size, colors, + icon: icon ?? defaultIcon, iconRight: true, isDisabled: isDisabled, border: border), + ], + ); +} + +Widget _getZetaButtonExample(ZetaButtonType buttonType, ZetaWidgetSize size, ZetaButtonColors colors, + {BorderType border = BorderType.rounded, IconData? icon, bool iconRight = false, bool isDisabled = false}) { + print(buttonType); + if (buttonType == ZetaButtonType.filled) + return ZetaButton.filled( + label: 'Button', + icon: icon, + iconOnRight: iconRight, + borderType: border, + size: size, + colors: colors, + onPressed: isDisabled ? null : () {}, + ); + return ZetaButton.outlined( + label: 'Button', + icon: icon, + iconOnRight: iconRight, + borderType: border, + size: size, + colors: colors, + onPressed: isDisabled ? null : () {}, + ); +} + +class BuildExampleButtonColors { + BuildExampleButtonColors({required this.theme}); + + final Zeta theme; + + ZetaButtonColors get primaryColors { + return ZetaButtonColors( + backgroundColor: ZetaColorBase.blue.shade60, + foregroundColor: ZetaColorBase.greyCool.shade20, + actionColor: ZetaColorBase.blue.shade90, + backgroundDisabled: ZetaColorBase.greyCool.shade30, + foregroundDisabled: ZetaColorBase.greyCool.shade50); + } + + ZetaButtonColors get primaryVariantColors { + return ZetaButtonColors( + backgroundColor: Color(0xFFFFD200), + foregroundColor: ZetaColorBase.greyCool.shade90, + actionColor: Color(0xFFC29500), + backgroundDisabled: ZetaColorBase.greyCool.shade30, + foregroundDisabled: ZetaColorBase.greyCool.shade50); + } + + ZetaButtonColors get negativeColors { + return ZetaButtonColors( + backgroundColor: ZetaColorBase.red.shade60, + foregroundColor: ZetaColorBase.greyCool.shade20, + actionColor: ZetaColorBase.red.shade80, + backgroundDisabled: ZetaColorBase.greyCool.shade30, + foregroundDisabled: ZetaColorBase.greyCool.shade50); + } + + ZetaButtonColors get outlined { + return ZetaButtonColors( + foregroundColor: ZetaColorBase.blue, + actionColor: ZetaColorBase.greyCool.shade30, + backgroundDisabled: ZetaColorBase.greyCool.shade30, + foregroundDisabled: ZetaColorBase.greyCool.shade50, + borderColor: ZetaColorBase.blue); + } + + ZetaButtonColors get outlinedSubtle { + return ZetaButtonColors( + foregroundColor: theme.colors.textDefault, + actionColor: ZetaColorBase.greyCool.shade50, + backgroundDisabled: ZetaColorBase.greyCool.shade30, + foregroundDisabled: ZetaColorBase.greyCool.shade50, + iconColor: theme.colors.textDefault, + borderColor: theme.colors.borderDefault); + } + + ZetaButtonColors get textColors { + return ZetaButtonColors( + foregroundColor: ZetaColorBase.blue, + actionColor: ZetaColorBase.greyCool.shade30, + backgroundDisabled: ZetaColorBase.greyCool.shade30, + foregroundDisabled: ZetaColorBase.greyCool.shade50); + } + + ZetaButtonColors get textInverseColor { + return ZetaButtonColors( + foregroundColor: ZetaColorBase.blue.shade40, + actionColor: ZetaColorBase.black, + backgroundDisabled: Colors.transparent, + foregroundDisabled: ZetaColorBase.greyCool); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock index 8e749b4c..5dd94b1f 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+4" + version: "0.1.1+6" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/button_test.dart b/example/test/button_test.dart new file mode 100644 index 00000000..5ea80e6b --- /dev/null +++ b/example/test/button_test.dart @@ -0,0 +1,40 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:flutter/material.dart'; + +import 'test_components.dart'; + +void main() { + group('ZetaButton Tests', () { + testWidgets('Initializes with correct Label and Icon', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaButton( + colors: ZetaButtonColors(), + onPressed: () {}, + label: 'Test Button', + icon: Icons.star, + )), + ); + + expect(find.text('Test Button'), findsOneWidget); + expect(find.byIcon(Icons.star), findsOneWidget); + }); + }); + + testWidgets('Triggers callback on tap', (WidgetTester tester) async { + bool callbackTriggered = false; + await tester.pumpWidget( + TestWidget( + widget: ZetaButton( + colors: ZetaButtonColors(), + onPressed: () => callbackTriggered = true, + label: 'Test Button', + )), + ); + await tester.tap(find.byType(ZetaButton)); + await tester.pump(); + + expect(callbackTriggered, isTrue); + }); +} diff --git a/example/widgetbook/components/button_widgetbook.dart b/example/widgetbook/components/button_widgetbook.dart new file mode 100644 index 00000000..75df80a2 --- /dev/null +++ b/example/widgetbook/components/button_widgetbook.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/button_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent buttonWidgetBook() { + return WidgetbookComponent( + name: 'Button', + useCases: [ + WidgetbookUseCase( + name: 'Button Rounded', + builder: (context) => SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: roundedButtonsExample(BuildExampleButtonColors(theme: Zeta.of(context))), + ), + ), + WidgetbookUseCase( + name: 'Button Sharp', + builder: (context) => SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: sharpButtonsExample(BuildExampleButtonColors(theme: Zeta.of(context))), + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index afd3d11b..985f108e 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -4,6 +4,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; import 'components/avatar_widgetbook.dart'; import 'components/badge_widgetbook.dart'; +import 'components/button_widgetbook.dart'; import 'components/checkbox_widgetbook.dart'; import 'components/color_widgetbook.dart'; import 'components/grid_widgetbook.dart'; @@ -37,7 +38,8 @@ class HotReload extends StatelessWidget { priorityPillWidgetBook(), workcloudIndicatorWidgetBook(), avatarWidgetBook(), - checkboxWidgetBook() + checkboxWidgetBook(), + buttonWidgetBook() ], ), ], diff --git a/lib/src/components/button.dart b/lib/src/components/button.dart new file mode 100644 index 00000000..f0fd45f4 --- /dev/null +++ b/lib/src/components/button.dart @@ -0,0 +1,241 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; + +///Colors for the [ZetaButton] widget +class ZetaButtonColors extends ZetaWidgetColor { + ///Construct [ZetaButtonColors] + const ZetaButtonColors({ + this.actionColor, + this.backgroundDisabled = ZetaColorBase.greyCool, + this.foregroundDisabled = ZetaColorBase.greyWarm, + this.borderColor = Colors.transparent, + this.iconColor, + super.backgroundColor = Colors.transparent, + super.foregroundColor = Colors.black12, + }); + + ///Defines the color used when the Button is pressed + final Color? actionColor; + + ///The color for the border when the [ZetaButton] is of type 'outlined' + final Color borderColor; + + ///The color for the icon + ///If color is not set, default color will be [foregroundColor] + final Color? iconColor; + + ///Color for the [ZetaButton] when it is disabled + final Color backgroundDisabled; + + ///Color for the [ZetaButton] icon and text when it is disabled + final Color foregroundDisabled; +} + +///Button types +enum ZetaButtonType { + ///Standard button with background color + filled, + + ///Button with border + outlined, +} + +///Zeta Button +class ZetaButton extends StatelessWidget { + ///Constructs [ZetaButton] + const ZetaButton({ + required this.label, + required this.colors, + this.icon, + this.onPressed, + this.iconOnRight = false, + this.type = ZetaButtonType.filled, + this.size = ZetaWidgetSize.large, + this.borderType = BorderType.rounded, + super.key, + }); + + ///Constructor for [ZetaButton] for type 'filled' + factory ZetaButton.filled({ + required String label, + required ZetaButtonColors colors, + IconData? icon, + VoidCallback? onPressed, + bool iconOnRight = false, + ZetaWidgetSize size = ZetaWidgetSize.small, + BorderType borderType = BorderType.rounded, + }) => + ZetaButton( + label: label, + icon: icon, + onPressed: onPressed, + iconOnRight: iconOnRight, + size: size, + colors: colors, + borderType: borderType, + ); + + ///Constructor for [ZetaButton] for type 'outlined' + factory ZetaButton.outlined({ + required String label, + required ZetaButtonColors colors, + IconData? icon, + VoidCallback? onPressed, + bool iconOnRight = false, + ZetaWidgetSize size = ZetaWidgetSize.small, + BorderType borderType = BorderType.rounded, + }) => + ZetaButton( + label: label, + icon: icon, + onPressed: onPressed, + iconOnRight: iconOnRight, + size: size, + colors: colors, + borderType: borderType, + type: ZetaButtonType.outlined, + ); + + ///Button label + final String label; + + ///The icon for the button + final IconData? icon; + + ///Called when the button is tapped or otherwise activated. + final VoidCallback? onPressed; + + ///Determines if the icon should be on the left or right side + ///Defaults to 'false' (Left icon) + final bool iconOnRight; + + ///The coloring type of the button + final ZetaButtonType type; + + ///Colors for the button + final ZetaButtonColors colors; + + ///Whether or not the button is sharp or rounded + ///Defaults to rounded + final BorderType borderType; + + ///Size of the button + ///Defaults to large + final ZetaWidgetSize size; + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: onPressed, + style: _buttonStyle(), + child: _buildButtonContent(), + ); + } + + Widget _buildButtonContent() { + List children = []; + if (icon != null) { + children + ..add(_buildIcon()) + ..add(const SizedBox(width: Dimensions.x2)); + } + children.add(_buildLabel()); + if (iconOnRight) children = children.reversed.toList(); + return IntrinsicWidth( + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: children, + ), + ); + } + + Widget _buildLabel() => Text(label, style: _getTextStyle()); + + Widget _buildIcon() => Transform.translate( + offset: const Offset(0, -1), + child: Icon( + icon, + color: onPressed != null ? (colors.iconColor ?? colors.foregroundColor) : colors.foregroundDisabled, + size: _iconSize(), + ), + ); + + ButtonStyle _buttonStyle() { + return ElevatedButton.styleFrom( + minimumSize: _getButtonSize(), + elevation: 0, + padding: _buttonPadding(), + shape: RoundedRectangleBorder(borderRadius: _getBorderRadius()), + ).copyWith( + backgroundColor: MaterialStateProperty.resolveWith( + (states) { + if (states.contains(MaterialState.disabled)) { + return colors.backgroundDisabled; + } + return colors.backgroundColor; + }, + ), + foregroundColor: MaterialStateProperty.resolveWith( + (states) { + if (states.contains(MaterialState.disabled)) { + return colors.foregroundDisabled; + } + return colors.foregroundColor; + }, + ), + overlayColor: MaterialStateProperty.resolveWith((Set states) { + if (states.contains(MaterialState.pressed)) return colors.actionColor; + return null; + }), + side: MaterialStateProperty.resolveWith((Set states) { + if (type == ZetaButtonType.filled) return null; + if (states.contains(MaterialState.disabled)) { + return BorderSide(color: colors.foregroundDisabled); + } + return BorderSide(color: colors.borderColor); + }), + ); + } + + BorderRadius _getBorderRadius() => + borderType == BorderType.rounded ? BorderRadius.circular(Dimensions.x1) : BorderRadius.zero; + + TextStyle _getTextStyle() => size == ZetaWidgetSize.small ? ZetaText.zetaLabelMedium : ZetaText.zetaLabelLarge; + + double _iconSize() => size == ZetaWidgetSize.small ? Dimensions.x4 : Dimensions.x5; + + EdgeInsets _buttonPadding() { + if (size == ZetaWidgetSize.small) { + return const EdgeInsets.fromLTRB(10, 6, 10, 6); + } else if (size == ZetaWidgetSize.medium) { + return const EdgeInsets.fromLTRB(14, 8, 14, 8); + } + return const EdgeInsets.fromLTRB(20, 12, 20, 12); + } + + Size _getButtonSize() { + if (size == ZetaWidgetSize.small) { + return const Size(68, 32); + } else if (size == ZetaWidgetSize.medium) { + return const Size(82, 40); + } + return const Size(98, 48); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(StringProperty('label', label)) + ..add(DiagnosticsProperty('icon', icon)) + ..add(ObjectFlagProperty.has('onPressed', onPressed)) + ..add(DiagnosticsProperty('iconOnRight', iconOnRight)) + ..add(DiagnosticsProperty('colors', colors)) + ..add(EnumProperty('type', type)) + ..add(EnumProperty('borderType', borderType)) + ..add(EnumProperty('size', size)); + } +} diff --git a/lib/src/utils/enums.dart b/lib/src/utils/enums.dart index c4ace7b2..d183631f 100644 --- a/lib/src/utils/enums.dart +++ b/lib/src/utils/enums.dart @@ -30,6 +30,18 @@ enum WidgetSeverity { custom } +/// [ZetaWidgetSize] size +enum ZetaWidgetSize { + /// large + large, + + /// medium + medium, + + /// small + small, +} + ///Widget Colors class ZetaWidgetColor { ///Constructs [ZetaWidgetColor]. @@ -44,15 +56,3 @@ class ZetaWidgetColor { ///foregroundColor Color final Color foregroundColor; } - -///Zeta Widget Size -enum ZetaWidgetSize { - /// [large] - large, - - /// [medium] - medium, - - /// [small] - small, -} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 32db711e..4b0c1b29 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -3,6 +3,7 @@ library zeta_flutter; export 'src/components/avatar.dart'; export 'src/components/badge.dart'; +export 'src/components/button.dart'; export 'src/components/checkbox.dart'; export 'src/components/grid.dart'; export 'src/components/indicator.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index fbac203a..95cf3416 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+6 +version: 0.1.1+7 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. From 541ec633f31f117b685671a33342e57c89823434 Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Mon, 18 Dec 2023 18:41:56 +0200 Subject: [PATCH 17/41] force Material 3 (#38) * force Material 3 * [automated commit] lint format and import sort --------- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions --- CHANGELOG.md | 80 +++++++++++++++++++++++-------- example/lib/main.dart | 3 +- lib/src/components/indicator.dart | 2 +- pubspec.yaml | 2 +- 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 970ade36..b7174cb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,40 @@ +## [0.1.1+8] - 2023-12-18 +### :flying_saucer: Other Changes +- [`4ca71f3`](https://github.com/zebratechnologies/zeta-flutter/commit/4ca71f3f83535e55c3af36961a5332fced0ecdbf) - Button component ([#36](https://github.com/zebratechnologies/zeta-flutter/pull/36)) + +* initial + +* format_error + +* [automated commit] lint format and import sort + +* button component optimizations + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* colors change + +* colors change + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`ba9062b`](https://github.com/zebratechnologies/zeta-flutter/commit/ba9062bb2268310a8c22d5230227c04afa178166) - force Material 3 ([#38](https://github.com/zebratechnologies/zeta-flutter/pull/38)) + +* force Material 3 + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + ## [0.1.1+7] - 2023-12-18 ### :flying_saucer: Other Changes - [`ac2b269`](https://github.com/zebratechnologies/zeta-flutter/commit/ac2b269c5806d2af310a063231abc1e412aea1a1) - fix the border of the indicator component ([#31](https://github.com/zebratechnologies/zeta-flutter/pull/31)) @@ -28,26 +65,26 @@ Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - [`cb330c7`](https://github.com/zebratechnologies/zeta-flutter/commit/cb330c7c1952ca2493b5d6c9272e2ade1050f53b) - Button component ([#36](https://github.com/zebratechnologies/zeta-flutter/pull/36)) -* initial - -* format_error - -* [automated commit] lint format and import sort - -* button component optimizations - -* [automated commit] lint format and import sort - -* [automated commit] lint format and import sort - -* colors change - -* colors change - -* [automated commit] lint format and import sort - ---------- - +* initial + +* format_error + +* [automated commit] lint format and import sort + +* button component optimizations + +* [automated commit] lint format and import sort + +* [automated commit] lint format and import sort + +* colors change + +* colors change + +* [automated commit] lint format and import sort + +--------- + Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* @@ -873,4 +910,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+4]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+3...0.1.1+4 [0.1.1+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+4...0.1.1+5 [0.1.1+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+5...0.1.1+6 -[0.1.1+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+6...0.1.1+7 \ No newline at end of file +[0.1.1+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+6...0.1.1+7 +[0.1.1+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+7...0.1.1+8 \ No newline at end of file diff --git a/example/lib/main.dart b/example/lib/main.dart index 75e344b5..aa8df680 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -49,12 +49,13 @@ class ZetaExample extends StatelessWidget { routerConfig: router, themeMode: themeMode, theme: ThemeData( - useMaterial3: false, + useMaterial3: true, fontFamily: themeData.fontFamily, scaffoldBackgroundColor: light.background, colorScheme: light, ), darkTheme: ThemeData( + useMaterial3: true, fontFamily: themeData.fontFamily, scaffoldBackgroundColor: dark.background, colorScheme: dark, diff --git a/lib/src/components/indicator.dart b/lib/src/components/indicator.dart index caae698f..4f83669e 100644 --- a/lib/src/components/indicator.dart +++ b/lib/src/components/indicator.dart @@ -227,7 +227,7 @@ class _InnerContent extends StatelessWidget { textAlign: strVal.length == 1 ? TextAlign.center : TextAlign.right, style: TextStyle( fontSize: fontSize, - // height: .9, + height: .9, letterSpacing: -0.5, color: foregroundColor ?? defaultColor, ), diff --git a/pubspec.yaml b/pubspec.yaml index 95cf3416..d842ce81 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+7 +version: 0.1.1+8 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. From c79686a8221a029280332e144da3fdb6eca0ead8 Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Mon, 18 Dec 2023 18:50:04 +0200 Subject: [PATCH 18/41] Tag component (#37) * initial * inital * initial * tag component * tag component * [automated commit] lint format and import sort --------- Co-authored-by: github-actions Co-authored-by: Atanas Yordanov --- CHANGELOG.md | 49 ++++- example/lib/home.dart | 2 + example/lib/pages/tag_example.dart | 49 +++++ example/pubspec.lock | 46 ++-- example/test/tag_test.dart | 40 ++++ .../widgetbook/components/tag_widgetbook.dart | 20 ++ example/widgetbook/widgetbook.dart | 2 + lib/src/components/tag.dart | 205 ++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 10 files changed, 384 insertions(+), 32 deletions(-) create mode 100644 example/lib/pages/tag_example.dart create mode 100644 example/test/tag_test.dart create mode 100644 example/widgetbook/components/tag_widgetbook.dart create mode 100644 lib/src/components/tag.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index b7174cb8..e888ab28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,35 @@ +## [0.1.1+9] - 2023-12-18 +### :flying_saucer: Other Changes +- [`541ec63`](https://github.com/zebratechnologies/zeta-flutter/commit/541ec633f31f117b685671a33342e57c89823434) - force Material 3 ([#38](https://github.com/zebratechnologies/zeta-flutter/pull/38)) + +* force Material 3 + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`0be43ac`](https://github.com/zebratechnologies/zeta-flutter/commit/0be43acce7c8f3b69a778f95420f542f92e725cf) - Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) + +* initial + +* inital + +* initial + +* tag component + +* tag component + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions +Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + ## [0.1.1+8] - 2023-12-18 ### :flying_saucer: Other Changes - [`4ca71f3`](https://github.com/zebratechnologies/zeta-flutter/commit/4ca71f3f83535e55c3af36961a5332fced0ecdbf) - Button component ([#36](https://github.com/zebratechnologies/zeta-flutter/pull/36)) @@ -25,13 +57,13 @@ Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`ba9062b`](https://github.com/zebratechnologies/zeta-flutter/commit/ba9062bb2268310a8c22d5230227c04afa178166) - force Material 3 ([#38](https://github.com/zebratechnologies/zeta-flutter/pull/38)) -* force Material 3 - -* [automated commit] lint format and import sort - ---------- - -Co-authored-by: Atanas Yordanov +* force Material 3 + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -911,4 +943,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+5]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+4...0.1.1+5 [0.1.1+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+5...0.1.1+6 [0.1.1+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+6...0.1.1+7 -[0.1.1+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+7...0.1.1+8 \ No newline at end of file +[0.1.1+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+7...0.1.1+8 +[0.1.1+9]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+8...0.1.1+9 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index d4487a0f..0d7f7eef 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -16,6 +16,7 @@ import 'package:zeta_example/pages/icons_example.dart'; import 'package:zeta_example/pages/indicator_example.dart'; import 'package:zeta_example/pages/spacing_example.dart'; import 'package:zeta_example/pages/status_label_example.dart'; +import 'package:zeta_example/pages/tag_example.dart'; import 'package:zeta_example/pages/typography_example.dart'; import 'package:zeta_example/pages/workcloud_indicator_example.dart'; import 'package:zeta_example/widgets.dart'; @@ -38,6 +39,7 @@ final List components = [ Component(IconsExample.name, (context) => const IconsExample()), Component(IndicatorExample.name, (context) => const IndicatorExample()), Component(LabelExample.name, (context) => const LabelExample()), + Component(TagExample.name, (context) => const TagExample()), Component(BadgeExample.name, (context) => const BadgeExample()), Component(PriorityPillExample.name, (context) => const PriorityPillExample()), Component(WorkcloudIndicatorExample.name, (context) => const WorkcloudIndicatorExample()), diff --git a/example/lib/pages/tag_example.dart b/example/lib/pages/tag_example.dart new file mode 100644 index 00000000..f24bdb60 --- /dev/null +++ b/example/lib/pages/tag_example.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class TagExample extends StatelessWidget { + static const String name = 'Tag'; + + const TagExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: TagExample.name, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [tagsRowLeft, tagsRowRight], + ), + ); + } + + static Widget get tagsRowLeft => Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ZetaTag.left( + label: 'Tag', + borderType: BorderType.sharp, + ), + ZetaTag.left( + label: 'Tag', + borderType: BorderType.rounded, + ) + ], + ); + + static Widget get tagsRowRight => Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ZetaTag.right( + label: 'Tag', + borderType: BorderType.sharp, + ), + ZetaTag.right( + label: 'Tag', + borderType: BorderType.rounded, + ) + ], + ); +} diff --git a/example/pubspec.lock b/example/pubspec.lock index 5dd94b1f..cfb9088b 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" crypto: dependency: transitive description: @@ -164,10 +164,10 @@ packages: dependency: transitive description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.2" http_parser: dependency: transitive description: @@ -220,10 +220,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" nested: dependency: transitive description: @@ -372,10 +372,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_windows: dependency: transitive description: @@ -425,18 +425,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -449,10 +449,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.0+1" term_glyph: dependency: transitive description: @@ -465,10 +465,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" typed_data: dependency: transitive description: @@ -497,18 +497,18 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" widgetbook: dependency: "direct dev" description: name: widgetbook - sha256: "37bb71322ed2b024b4b321f9ac0791f6b4510a9abcd42a108c11bec97ac4688a" + sha256: bdbfdc517923218394f11ad4e004a7e3d45672047e9d87f52833ac294366232d url: "https://pub.dev" source: hosted - version: "3.5.0" + version: "3.7.0" win32: dependency: transitive description: @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+6" + version: "0.1.1+8" sdks: - dart: ">=3.1.0 <4.0.0" - flutter: ">=3.10.0" + dart: ">=3.2.0 <4.0.0" + flutter: ">=3.16.0" diff --git a/example/test/tag_test.dart b/example/test/tag_test.dart new file mode 100644 index 00000000..6925b94c --- /dev/null +++ b/example/test/tag_test.dart @@ -0,0 +1,40 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import 'test_components.dart'; + +void main() { + group('ZetaCheckbox Tests', () { + testWidgets('Initializes with correct parameters', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaTag.right( + label: 'Tag', + ), + ), + ); + + expect(find.text('Tag'), findsOneWidget); + }); + + testWidgets('ZetaTag handles direction correctly', (WidgetTester tester) async { + const widgetLeft = TestWidget( + widget: ZetaTag( + label: 'Tag', + direction: ZetaTagDirection.left, + )); + + const widgetRight = TestWidget( + widget: ZetaTag( + label: 'Tag', + direction: ZetaTagDirection.right, + )); + + await tester.pumpWidget(widgetLeft); + expect(find.byType(ZetaTag), findsOneWidget); + + await tester.pumpWidget(widgetRight); + expect(find.byType(ZetaTag), findsOneWidget); + }); + }); +} diff --git a/example/widgetbook/components/tag_widgetbook.dart b/example/widgetbook/components/tag_widgetbook.dart new file mode 100644 index 00000000..091e59f5 --- /dev/null +++ b/example/widgetbook/components/tag_widgetbook.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/tag_example.dart'; + +WidgetbookComponent tagWidgetBook() { + return WidgetbookComponent( + name: 'Tag', + useCases: [ + WidgetbookUseCase( + name: 'Tag', + builder: (context) => Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [TagExample.tagsRowLeft, TagExample.tagsRowRight], + )), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 985f108e..5e039964 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -12,6 +12,7 @@ import 'components/indicator_widgetbook.dart'; import 'components/priority_pill_widgetbook.dart'; import 'components/spacing_widgetbook.dart'; import 'components/status_label_widgetbook.dart'; +import 'components/tag_widgetbook.dart'; import 'components/typography_widgetbook.dart'; import 'components/workcloud_indicator_widgetbook.dart'; import 'utils/zebra.dart'; @@ -33,6 +34,7 @@ class HotReload extends StatelessWidget { textWidgetBook(), colorWidgetBook(), statusLabelWidgetBook(), + tagWidgetBook(), badgeWidgetBook(), indicatorWidgetBook(), priorityPillWidgetBook(), diff --git a/lib/src/components/tag.dart b/lib/src/components/tag.dart new file mode 100644 index 00000000..07f3aee0 --- /dev/null +++ b/lib/src/components/tag.dart @@ -0,0 +1,205 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; + +///Tag Direction options +enum ZetaTagDirection { + ///facing left + left, + + ///facing right + right +} + +///Zeta Tag +class ZetaTag extends StatelessWidget { + ///Constructs [ZetaTag] + const ZetaTag({ + this.direction = ZetaTagDirection.left, + this.borderType = BorderType.sharp, + required this.label, + super.key, + }); + + ///Constructor [ZetaTag] left sided + factory ZetaTag.left({ + BorderType borderType = BorderType.sharp, + required String label, + }) => + ZetaTag( + borderType: borderType, + label: label, + ); + + ///Constructor [ZetaTag] right sided + factory ZetaTag.right({ + BorderType borderType = BorderType.sharp, + required String label, + }) => + ZetaTag( + direction: ZetaTagDirection.right, + borderType: borderType, + label: label, + ); + + /// Fixed container size + static const Size _containerSize = Size(36, 28); + + ///Determines the direction of the tag + /// + /// Defaults to left + final ZetaTagDirection direction; + + ///Border type of the widget + ///Defaults to sharp + final BorderType borderType; + + ///tag label + final String label; + + @override + Widget build(BuildContext context) { + return Row( + children: [ + if (direction == ZetaTagDirection.right) ...[ + _buildCustomPaint(context), + ], + _buildContainer(context), + if (direction == ZetaTagDirection.left) ...[ + _buildCustomPaint(context), + ], + ], + ); + } + + BorderRadius _getBorderRadius() { + if (borderType == BorderType.sharp) return BorderRadius.zero; + if (direction == ZetaTagDirection.right) { + return const BorderRadius.only( + topRight: Radius.circular(2), + bottomRight: Radius.circular(2), + ); + } else { + return const BorderRadius.only( + topLeft: Radius.circular(2), + bottomLeft: Radius.circular(2), + ); + } + } + + Widget _buildContainer(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: _getWidgetColor(context), + borderRadius: _getBorderRadius(), + ), + height: _containerSize.height, + constraints: BoxConstraints(minWidth: _containerSize.width), + child: Center( + child: FittedBox( + child: Padding( + padding: const EdgeInsets.fromLTRB( + Dimensions.x2, + 1, + Dimensions.x2, + 1, + ), + child: Text( + label, + style: ZetaText.zetaBodyMedium, + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + ); + } + + Widget _buildCustomPaint(BuildContext context) { + return Stack( + children: [ + CustomPaint( + size: const Size(Dimensions.x3, Dimensions.x7), + painter: _TagPainter( + color: _getWidgetColor(context), + direction: direction, + borderType: borderType, + ), + ), + // Additional widgets if needed + ], + ); + } + + Color _getWidgetColor(BuildContext context) => + Zeta.of(context).themeMode == ThemeMode.dark ? ZetaColorBase.greyWarm.shade90 : ZetaColorBase.greyCool.shade30; + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('direction', direction)) + ..add(EnumProperty('borderType', borderType)) + ..add(StringProperty('label', label)); + } +} + +class _TagPainter extends CustomPainter { + const _TagPainter({ + required this.color, + required this.direction, + required this.borderType, + }); + + final Color color; + final ZetaTagDirection direction; + final BorderType borderType; + + @override + void paint(Canvas canvas, Size size) { + final Paint paint = Paint() + ..color = color + ..style = PaintingStyle.fill; + final path = _buildPath(size); + if (borderType != BorderType.sharp) _drawDot(canvas, size); + canvas.drawPath(path, paint); + } + + Path _buildPath(Size size) { + return direction == ZetaTagDirection.left ? _leftPath(size) : _rightPath(size); + } + + void _drawDot(Canvas canvas, Size size) { + final paint = Paint()..color = color; + const double dotSize = 1.7; + + Offset dotPosition; + if (direction == ZetaTagDirection.right) { + dotPosition = Offset(2, size.height / 2); + } else { + dotPosition = Offset(size.width - 2, size.height / 2); + } + + canvas.drawCircle(dotPosition, dotSize, paint); + } + + Path _leftPath(Size size) { + return Path() + ..moveTo(0, size.height) + ..lineTo(size.width, size.height / 2) + ..lineTo(0, 0) + ..close(); + } + + Path _rightPath(Size size) { + return Path() + ..moveTo(0, size.height / 2) + ..lineTo(size.width, 0) + ..lineTo(size.width, size.height) + ..close(); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 4b0c1b29..ed98a138 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -11,6 +11,7 @@ export 'src/components/priority_pill.dart'; export 'src/components/spacing.dart'; export 'src/components/status_label.dart'; export 'src/components/system_banner.dart'; +export 'src/components/tag.dart'; export 'src/components/text.dart'; export 'src/components/workcloud_indicator.dart'; export 'src/icons.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index d842ce81..626b82b7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+8 +version: 0.1.1+9 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. From c506b81c0f00b23192ddef4e484dabf8a0f36890 Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:14:29 +0200 Subject: [PATCH 19/41] Component accordion (#39) * first draft of the ZetaAccordion * create ZetaAccordion component * add icon padding * add list separator & margin * Tag component (#37) * initial * inital * initial * tag component * tag component * [automated commit] lint format and import sort --------- Co-authored-by: github-actions Co-authored-by: Atanas Yordanov * add comments and more examples * pubspec * [automated commit] lint format and import sort --------- Co-authored-by: Atanas Yordanov Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Co-authored-by: github-actions --- CHANGELOG.md | 77 +++++- example/lib/home.dart | 2 + example/lib/pages/accordion_example.dart | 94 +++++++ example/pubspec.lock | 38 +-- .../components/accordion_widgetbook.dart | 32 +++ example/widgetbook/widgetbook.dart | 2 + lib/src/components/accordion.dart | 242 ++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 9 files changed, 463 insertions(+), 27 deletions(-) create mode 100644 example/lib/pages/accordion_example.dart create mode 100644 example/widgetbook/components/accordion_widgetbook.dart create mode 100644 lib/src/components/accordion.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index e888ab28..53d9bf53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,35 @@ -## [0.1.1+9] - 2023-12-18 +## [0.1.1+10] - 2023-12-19 ### :flying_saucer: Other Changes -- [`541ec63`](https://github.com/zebratechnologies/zeta-flutter/commit/541ec633f31f117b685671a33342e57c89823434) - force Material 3 ([#38](https://github.com/zebratechnologies/zeta-flutter/pull/38)) +- [`c79686a`](https://github.com/zebratechnologies/zeta-flutter/commit/c79686a8221a029280332e144da3fdb6eca0ead8) - Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) -* force Material 3 +* initial + +* inital + +* initial + +* tag component + +* tag component * [automated commit] lint format and import sort --------- -Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* -- [`0be43ac`](https://github.com/zebratechnologies/zeta-flutter/commit/0be43acce7c8f3b69a778f95420f542f92e725cf) - Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) +Co-authored-by: github-actions +Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`df9eb66`](https://github.com/zebratechnologies/zeta-flutter/commit/df9eb66803c2f005099aa67a9394e520626401d3) - Component accordion ([#39](https://github.com/zebratechnologies/zeta-flutter/pull/39)) +* first draft of the ZetaAccordion + +* create ZetaAccordion component + +* add icon padding + +* add list separator & margin + +* Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) + * initial * inital @@ -27,6 +45,50 @@ Co-authored-by: github-actions *(commit by [@atanasy --------- Co-authored-by: github-actions +Co-authored-by: Atanas Yordanov + +* add comments and more examples + +* pubspec + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + +## [0.1.1+9] - 2023-12-18 +### :flying_saucer: Other Changes +- [`541ec63`](https://github.com/zebratechnologies/zeta-flutter/commit/541ec633f31f117b685671a33342e57c89823434) - force Material 3 ([#38](https://github.com/zebratechnologies/zeta-flutter/pull/38)) + +* force Material 3 + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`0be43ac`](https://github.com/zebratechnologies/zeta-flutter/commit/0be43acce7c8f3b69a778f95420f542f92e725cf) - Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) + +* initial + +* inital + +* initial + +* tag component + +* tag component + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* @@ -944,4 +1006,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+6]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+5...0.1.1+6 [0.1.1+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+6...0.1.1+7 [0.1.1+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+7...0.1.1+8 -[0.1.1+9]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+8...0.1.1+9 \ No newline at end of file +[0.1.1+9]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+8...0.1.1+9 +[0.1.1+10]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+9...0.1.1+10 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 0d7f7eef..e35ec980 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:zeta_example/pages/accordion_example.dart'; import 'package:zeta_example/pages/app_bar_example/app_bar_example.dart'; import 'package:zeta_example/pages/app_bar_example/default_app_bar.dart'; import 'package:zeta_example/pages/app_bar_example/negative_app_bar.dart'; @@ -50,6 +51,7 @@ final List components = [ Component(NegativeAppBarExample.name, (context) => const NegativeAppBarExample()), ]), Component(CheckBoxExample.name, (context) => const CheckBoxExample()), + Component(AccordionExample.name, (context) => const AccordionExample()), Component(ButtonExample.name, (context) => const ButtonExample()), ]; diff --git a/example/lib/pages/accordion_example.dart b/example/lib/pages/accordion_example.dart new file mode 100644 index 00000000..67a12e43 --- /dev/null +++ b/example/lib/pages/accordion_example.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class AccordionExample extends StatelessWidget { + static const String name = 'Accordion'; + + const AccordionExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: AccordionExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + Text('Default'), + const SizedBox(height: 20), + accordionDefaultExample, + const SizedBox(height: 40), + Text('Contained'), + const SizedBox(height: 20), + accordionContainedExample, + const SizedBox(height: 40), + Text('Sharp'), + const SizedBox(height: 20), + accordionSharpExample, + ], + ), + ), + ); + }, + ); + } + + static Widget get accordionDefaultExample => ZetaAccordion( + spaceBetween: 0, + children: [ + ZetaAccordionSection( + title: Text('Title Default Enabled'), + body: Column( + children: [ + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ], + ), + ), + ZetaAccordionSection( + disabled: true, + title: Text('Title Default Disabled'), + body: Text('...'), + ), + ], + ); + + static Widget get accordionContainedExample => ZetaAccordion( + contained: true, + children: [ + ZetaAccordionSection( + title: Text('Title Contained Enabled'), + body: Text( + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'), + ), + ZetaAccordionSection( + disabled: true, + title: Text('Title Contained Disabled'), + body: Text('...'), + ), + ], + ); + + static Widget get accordionSharpExample => ZetaAccordion( + contained: true, + rounded: false, + children: [ + ZetaAccordionSection( + title: Text('Title Contained Sharp Enabled'), + body: Center( + child: Icon(Icons.image_outlined, size: 300), + ), + ), + ZetaAccordionSection( + disabled: true, + title: Text('Title Contained Sharp Disabled'), + body: Text('...'), + ), + ], + ); +} diff --git a/example/pubspec.lock b/example/pubspec.lock index cfb9088b..357450c9 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.2" crypto: dependency: transitive description: @@ -164,10 +164,10 @@ packages: dependency: transitive description: name: http - sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.0" http_parser: dependency: transitive description: @@ -220,10 +220,10 @@ packages: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" nested: dependency: transitive description: @@ -372,10 +372,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.1" shared_preferences_windows: dependency: transitive description: @@ -425,18 +425,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" string_scanner: dependency: transitive description: @@ -465,10 +465,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.6.0" typed_data: dependency: transitive description: @@ -497,10 +497,10 @@ packages: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.1.4-beta" widgetbook: dependency: "direct dev" description: @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+8" + version: "0.1.1+9" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.1.0 <4.0.0" + flutter: ">=3.10.0" diff --git a/example/widgetbook/components/accordion_widgetbook.dart b/example/widgetbook/components/accordion_widgetbook.dart new file mode 100644 index 00000000..46a7477c --- /dev/null +++ b/example/widgetbook/components/accordion_widgetbook.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/accordion_example.dart'; + +WidgetbookComponent accordionWidgetBook() { + return WidgetbookComponent( + name: 'Accordion', + useCases: [ + WidgetbookUseCase( + name: 'Default', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: AccordionExample.accordionDefaultExample, + ), + ), + WidgetbookUseCase( + name: 'Contained', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: AccordionExample.accordionContainedExample, + ), + ), + WidgetbookUseCase( + name: 'Sharp', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: AccordionExample.accordionSharpExample, + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 5e039964..10870f1b 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -2,6 +2,7 @@ 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/badge_widgetbook.dart'; import 'components/button_widgetbook.dart'; @@ -41,6 +42,7 @@ class HotReload extends StatelessWidget { workcloudIndicatorWidgetBook(), avatarWidgetBook(), checkboxWidgetBook(), + accordionWidgetBook(), buttonWidgetBook() ], ), diff --git a/lib/src/components/accordion.dart b/lib/src/components/accordion.dart new file mode 100644 index 00000000..7c22121d --- /dev/null +++ b/lib/src/components/accordion.dart @@ -0,0 +1,242 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '../../zeta_flutter.dart'; + +/// Component [ZetaAccordion] +class ZetaAccordion extends StatelessWidget { + /// The constructor of the component [ZetaAccordion] + const ZetaAccordion({ + super.key, + required this.children, + this.separator, + this.spaceBetween = 20.0, + this.margin, + this.rounded = true, + this.contained = false, + }); + + /// List of [ZetaAccordionSection] to show in [ZetaAccordion] + final List children; + + /// Custom separator between the [ZetaAccordionSection]s in the list `children`. + /// Default is empty space with height of `spaceBetween`. + final Widget? separator; + + /// The height of the space between [ZetaAccordionSection]s `children`. + /// Default is 20. + final double spaceBetween; + + /// The space around the [ZetaAccordion]. Default is `zero`. + final EdgeInsets? margin; + + /// Sets rounded or sharp border of the containing box and the icon style. + /// Default is `true`. + final bool rounded; + + /// Determines if the [ZetaAccordionSection]s should be in a box. + /// Default is `false` + final bool contained; + + @override + Widget build(BuildContext context) { + return ListView.separated( + padding: margin ?? EdgeInsets.zero, + shrinkWrap: true, + itemCount: children.length, + itemBuilder: (context, index) => children[index].copyWith( + rounded: rounded, + contained: contained, + ), + separatorBuilder: (context, index) => separator ?? SizedBox(height: spaceBetween), + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('spaceBetween', spaceBetween)) + ..add(DiagnosticsProperty('margin', margin)) + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(DiagnosticsProperty('contained', contained)); + } +} + +/// The element for the `children` of [ZetaAccordion] +class ZetaAccordionSection extends StatefulWidget { + /// The constructor of the [ZetaAccordionSection] + const ZetaAccordionSection({ + super.key, + required this.title, + required this.body, + this.isOpen = false, + this.disabled = false, + this.rounded = true, + this.contained = false, + }); + + /// The header of the [ZetaAccordionSection]. + final Widget title; + + /// The content of the [ZetaAccordionSection]. + final Widget body; + + /// Sets the initial state of the [ZetaAccordionSection]. + /// Default is `false`. + final bool isOpen; + + /// Determines if [ZetaAccordionSection] should be disabled. + /// Default is `false`. + final bool disabled; + + /// Sets rounded or sharp border of the containing box and the icon style. + /// Default is `true`. + final bool rounded; + + /// Determines if the [ZetaAccordionSection]s should be in a box. + /// Default is `false` + final bool contained; + + @override + State createState() => _ZetaAccordionSectionState(); + + /// Creates another instance of the same [ZetaAccordionSection], + /// but with modified properties. + ZetaAccordionSection copyWith({ + bool rounded = true, + bool contained = false, + }) { + return ZetaAccordionSection( + title: title, + body: body, + isOpen: isOpen, + disabled: disabled, + rounded: rounded, + contained: contained, + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('isOpen', isOpen)) + ..add(DiagnosticsProperty('disabled', disabled)) + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(DiagnosticsProperty('contained', contained)); + } +} + +class _ZetaAccordionSectionState extends State with TickerProviderStateMixin { + late bool _isOpen; + late bool _disabled; + late final AnimationController _controller; + late final Animation _animation; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + duration: const Duration(milliseconds: 300), + reverseDuration: const Duration(milliseconds: 200), + vsync: this, + ); + _animation = CurvedAnimation( + parent: _controller, + curve: Curves.fastOutSlowIn, + ); + init(); + } + + @override + void didUpdateWidget(ZetaAccordionSection oldWidget) { + init(); + super.didUpdateWidget(oldWidget); + } + + void init() { + _isOpen = widget.isOpen; + _disabled = widget.disabled; + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final zetaColors = Zeta.of(context).colors; + + return DecoratedBox( + decoration: BoxDecoration( + border: widget.contained + ? Border.all( + color: _disabled ? zetaColors.borderDisabled : zetaColors.borderDefault, + ) + : null, + borderRadius: widget.rounded ? BorderRadius.circular(Dimensions.xxs) : null, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + InkWell( + onTap: _disabled + ? null + : () => setState(() { + if (_isOpen) { + _controller.reverse(); + _isOpen = false; + } else { + _isOpen = true; + _controller.forward(); + } + }), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + DefaultTextStyle( + style: TextStyle( + fontSize: 18, + height: 1.33, + fontWeight: FontWeight.w500, + color: _disabled ? zetaColors.textDisabled : zetaColors.textDefault, + ), + child: Flexible(child: widget.title), + ), + Padding( + padding: const EdgeInsets.only(left: 16), + child: Icon( + _isOpen + ? (widget.rounded ? ZetaIcons.remove_round : ZetaIcons.remove_sharp) + : (widget.rounded ? ZetaIcons.add_round : ZetaIcons.add_sharp), + color: _disabled ? zetaColors.iconDisabled : zetaColors.iconDefault, + ), + ), + ], + ), + ), + ), + SizeTransition( + sizeFactor: _animation, + axisAlignment: -1, + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), + child: DefaultTextStyle( + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: zetaColors.textDefault, + ), + child: widget.body, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index ed98a138..f42d8dcb 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -1,6 +1,7 @@ /// Zebra Design System (Zeta) - Flutter Component Library library zeta_flutter; +export 'src/components/accordion.dart'; export 'src/components/avatar.dart'; export 'src/components/badge.dart'; export 'src/components/button.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 626b82b7..bd3527a3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+9 +version: 0.1.1+10 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. From dcafe1f2f0436adf75e9cb36e0c4dd1bb8015def Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:48:11 +0200 Subject: [PATCH 20/41] fix sizings and replace icons with zeta icons (#43) * fix sizings and replace icons with zeta icons * [automated commit] lint format and import sort --------- Co-authored-by: github-actions --- CHANGELOG.md | 128 +++++++++++++++++------- example/lib/pages/checkbox_example.dart | 14 +-- lib/src/components/checkbox.dart | 23 +++-- pubspec.yaml | 2 +- 4 files changed, 116 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53d9bf53..5b8c2c1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ -## [0.1.1+10] - 2023-12-19 +## [0.1.1+11] - 2023-12-19 ### :flying_saucer: Other Changes -- [`c79686a`](https://github.com/zebratechnologies/zeta-flutter/commit/c79686a8221a029280332e144da3fdb6eca0ead8) - Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) +- [`c506b81`](https://github.com/zebratechnologies/zeta-flutter/commit/c506b81c0f00b23192ddef4e484dabf8a0f36890) - Component accordion ([#39](https://github.com/zebratechnologies/zeta-flutter/pull/39)) + +* first draft of the ZetaAccordion + +* create ZetaAccordion component + +* add icon padding + +* add list separator & margin + +* Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) * initial @@ -17,46 +27,89 @@ --------- Co-authored-by: github-actions -Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* -- [`df9eb66`](https://github.com/zebratechnologies/zeta-flutter/commit/df9eb66803c2f005099aa67a9394e520626401d3) - Component accordion ([#39](https://github.com/zebratechnologies/zeta-flutter/pull/39)) +Co-authored-by: Atanas Yordanov -* first draft of the ZetaAccordion - -* create ZetaAccordion component - -* add icon padding - -* add list separator & margin - -* Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) - -* initial - -* inital - -* initial - -* tag component - -* tag component - -* [automated commit] lint format and import sort - ---------- - -Co-authored-by: github-actions -Co-authored-by: Atanas Yordanov - -* add comments and more examples - -* pubspec +* add comments and more examples + +* pubspec + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`10a075e`](https://github.com/zebratechnologies/zeta-flutter/commit/10a075ed9dc7aac6021ccc08fde574f520b2fc9e) - fix sizings and replace icons with zeta icons ([#43](https://github.com/zebratechnologies/zeta-flutter/pull/43)) + +* fix sizings and replace icons with zeta icons * [automated commit] lint format and import sort --------- -Co-authored-by: Atanas Yordanov -Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + +## [0.1.1+10] - 2023-12-19 +### :flying_saucer: Other Changes +- [`c79686a`](https://github.com/zebratechnologies/zeta-flutter/commit/c79686a8221a029280332e144da3fdb6eca0ead8) - Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) + +* initial + +* inital + +* initial + +* tag component + +* tag component + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions +Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`df9eb66`](https://github.com/zebratechnologies/zeta-flutter/commit/df9eb66803c2f005099aa67a9394e520626401d3) - Component accordion ([#39](https://github.com/zebratechnologies/zeta-flutter/pull/39)) + +* first draft of the ZetaAccordion + +* create ZetaAccordion component + +* add icon padding + +* add list separator & margin + +* Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) + +* initial + +* inital + +* initial + +* tag component + +* tag component + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions +Co-authored-by: Atanas Yordanov + +* add comments and more examples + +* pubspec + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -1007,4 +1060,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+7]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+6...0.1.1+7 [0.1.1+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+7...0.1.1+8 [0.1.1+9]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+8...0.1.1+9 -[0.1.1+10]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+9...0.1.1+10 \ No newline at end of file +[0.1.1+10]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+9...0.1.1+10 +[0.1.1+11]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+10...0.1.1+11 \ No newline at end of file diff --git a/example/lib/pages/checkbox_example.dart b/example/lib/pages/checkbox_example.dart index 3d136332..a82ca833 100644 --- a/example/lib/pages/checkbox_example.dart +++ b/example/lib/pages/checkbox_example.dart @@ -31,18 +31,18 @@ class _CheckBoxExampleState extends State { ZetaCheckbox( value: isChecked, isEnabled: isEnabled, onChanged: (value) => setState(() => isChecked = value)), ElevatedButton( - child: const Text('Disable'), + child: Text(isEnabled ? 'Disable' : 'Enable'), onPressed: () => setState(() => isEnabled = !isEnabled), ) ], ), - Row(children: [const Text('Sharp Checkbox Enabled')]), + Row(children: [Text('Sharp Checkbox Enabled', style: ZetaText.zetaTitleLarge)]), getCheckBoxRow(isEnabled: true), - Row(children: [const Text('Sharp Checkbox Disabled')]), + Row(children: [Text('Sharp Checkbox Disabled', style: ZetaText.zetaTitleLarge)]), getCheckBoxRow(isEnabled: false), - Row(children: [const Text('Rounded Checkbox Enabled')]), + Row(children: [Text('Rounded Checkbox Enabled', style: ZetaText.zetaTitleLarge)]), getCheckBoxRow(isEnabled: true, isSharp: false), - Row(children: [const Text('Rounded Checkbox Disabled')]), + Row(children: [Text('Rounded Checkbox Disabled', style: ZetaText.zetaTitleLarge)]), getCheckBoxRow(isEnabled: false, isSharp: false), ], ), @@ -59,13 +59,13 @@ Row getCheckBoxRow({required bool isEnabled, bool isSharp = true}) { ZetaCheckbox( value: true, isEnabled: isEnabled, - label: 'Selected', + label: 'Label', borderType: isSharp ? BorderType.sharp : BorderType.rounded, onChanged: (value) => {}), ZetaCheckbox( value: false, isEnabled: isEnabled, - label: 'Indeterminate', + label: 'Label', borderType: isSharp ? BorderType.sharp : BorderType.rounded, onChanged: (value) => {}), ZetaCheckbox( diff --git a/lib/src/components/checkbox.dart b/lib/src/components/checkbox.dart index f29c5333..1bfb4b55 100644 --- a/lib/src/components/checkbox.dart +++ b/lib/src/components/checkbox.dart @@ -11,14 +11,14 @@ class ZetaCheckbox extends StatelessWidget { this.borderType = BorderType.sharp, this.label, this.labelStyle, - this.checkboxSize = const Size(25, 25), + this.checkboxSize = const Size(20, 20), this.selectedColor, this.unselectedColor, this.unselectedBorderColor, - this.unselectedBorderWidth = 2.5, + this.unselectedBorderWidth = 2, this.disabledColor, this.isEnabled = true, - this.iconSize = 18.0, + this.iconSize = 15.0, super.key, }) : assert(iconSize > 0, 'Icon size must be greater than 0'); @@ -108,7 +108,7 @@ class ZetaCheckbox extends StatelessWidget { padding: const EdgeInsets.only(left: Dimensions.s), child: Text( label!, - style: labelStyle ?? ZetaText.zetaTitleMedium, + style: labelStyle ?? ZetaText.zetaBodyLarge, ), ), ), @@ -130,7 +130,7 @@ class ZetaCheckbox extends StatelessWidget { width: unselectedBorderWidth, ), borderRadius: BorderRadius.circular( - borderType == BorderType.rounded ? 4.0 : 0.0, + borderType == BorderType.rounded ? 2.0 : 0.0, ), ), width: checkboxSize.width, @@ -154,12 +154,23 @@ class ZetaCheckbox extends StatelessWidget { Widget _getCheckboxIcon(Zeta theme) { if (value == null) return const SizedBox.shrink(); return Icon( - value! ? Icons.check : Icons.remove, + _getIcon(), color: isEnabled ? theme.colors.white : theme.colors.textDisabled, size: iconSize, ); } + IconData _getIcon() { + final isRounded = borderType == BorderType.rounded; + return value! + ? isRounded + ? ZetaIcons.check_round + : ZetaIcons.check_sharp + : isRounded + ? ZetaIcons.remove_round + : ZetaIcons.remove_sharp; + } + Color _getCheckboxBackgroundColor(Zeta theme) { if (!isEnabled) return disabledColor ?? theme.colors.surfaceDisabled; if (value == null) return unselectedColor ?? theme.colors.surfaceSecondary; diff --git a/pubspec.yaml b/pubspec.yaml index bd3527a3..da9688fa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+10 +version: 0.1.1+11 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. From 51caca71fce57681cabeb82e979499da9a16f4c1 Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Wed, 20 Dec 2023 10:04:22 +0200 Subject: [PATCH 21/41] Menu Items - horizontal & vertical (#44) * Menu Items - horizontal & vertical * [automated commit] lint format and import sort --------- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions --- CHANGELOG.md | 38 +++- example/lib/home.dart | 2 + example/lib/pages/menu_items.dart | 112 +++++++++++ .../components/menu_items_widgetbook.dart | 25 +++ example/widgetbook/widgetbook.dart | 3 + lib/src/components/menu_items.dart | 177 ++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 8 files changed, 352 insertions(+), 8 deletions(-) create mode 100644 example/lib/pages/menu_items.dart create mode 100644 example/widgetbook/components/menu_items_widgetbook.dart create mode 100644 lib/src/components/menu_items.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b8c2c1b..fa78054e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +## [0.1.1+12] - 2023-12-20 +### :flying_saucer: Other Changes +- [`dcafe1f`](https://github.com/zebratechnologies/zeta-flutter/commit/dcafe1f2f0436adf75e9cb36e0c4dd1bb8015def) - fix sizings and replace icons with zeta icons ([#43](https://github.com/zebratechnologies/zeta-flutter/pull/43)) + +* fix sizings and replace icons with zeta icons + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`231fa4b`](https://github.com/zebratechnologies/zeta-flutter/commit/231fa4b860d4ecbb551ba7ec65b783d26fed43a0) - Menu Items - horizontal & vertical ([#44](https://github.com/zebratechnologies/zeta-flutter/pull/44)) + +* Menu Items - horizontal & vertical + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + ## [0.1.1+11] - 2023-12-19 ### :flying_saucer: Other Changes - [`c506b81`](https://github.com/zebratechnologies/zeta-flutter/commit/c506b81c0f00b23192ddef4e484dabf8a0f36890) - Component accordion ([#39](https://github.com/zebratechnologies/zeta-flutter/pull/39)) @@ -42,12 +65,12 @@ Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.gi Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - [`10a075e`](https://github.com/zebratechnologies/zeta-flutter/commit/10a075ed9dc7aac6021ccc08fde574f520b2fc9e) - fix sizings and replace icons with zeta icons ([#43](https://github.com/zebratechnologies/zeta-flutter/pull/43)) -* fix sizings and replace icons with zeta icons - -* [automated commit] lint format and import sort - ---------- - +* fix sizings and replace icons with zeta icons + +* [automated commit] lint format and import sort + +--------- + Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* @@ -1061,4 +1084,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+8]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+7...0.1.1+8 [0.1.1+9]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+8...0.1.1+9 [0.1.1+10]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+9...0.1.1+10 -[0.1.1+11]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+10...0.1.1+11 \ No newline at end of file +[0.1.1+11]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+10...0.1.1+11 +[0.1.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+11...0.1.1+12 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index e35ec980..b7250a2d 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -12,6 +12,7 @@ import 'package:zeta_example/pages/button_example.dart'; import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/checkbox_example.dart'; import 'package:zeta_example/pages/grid_example.dart'; +import 'package:zeta_example/pages/menu_items.dart'; import 'package:zeta_example/pages/priority_pill_example.dart'; import 'package:zeta_example/pages/icons_example.dart'; import 'package:zeta_example/pages/indicator_example.dart'; @@ -53,6 +54,7 @@ final List components = [ Component(CheckBoxExample.name, (context) => const CheckBoxExample()), Component(AccordionExample.name, (context) => const AccordionExample()), Component(ButtonExample.name, (context) => const ButtonExample()), + Component(MenuItemsExample.name, (context) => const MenuItemsExample()), ]; class Home extends StatefulWidget { diff --git a/example/lib/pages/menu_items.dart b/example/lib/pages/menu_items.dart new file mode 100644 index 00000000..adda489b --- /dev/null +++ b/example/lib/pages/menu_items.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class MenuItemsExample extends StatelessWidget { + static const String name = 'MenuItems'; + + const MenuItemsExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: MenuItemsExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + Text('Horizontal'), + const SizedBox(height: 20), + horizontalExample, + const SizedBox(height: 50), + Text('Vertical'), + const SizedBox(height: 20), + verticalExample, + ], + ), + ), + ); + }, + ); + } + + static Widget get horizontalExample => Column( + children: [ + ZetaMenuItem.horizontal( + label: Text('Menu Item'), + onTap: () {}, + ), + ZetaMenuItem.horizontal( + label: Text('Menu Item'), + leadingIcon: Icon(ZetaIcons.star_round), + onTap: () {}, + ), + ZetaMenuItem.horizontal( + label: Text('Menu Item'), + showTrailing: true, + onTap: () {}, + ), + ZetaMenuItem.horizontal( + label: Text('Menu Item'), + trailingIcon: Icon(Icons.fast_forward), + onTap: () {}, + ), + ZetaMenuItem.horizontal( + label: Text('Menu Item'), + leadingIcon: Icon(ZetaIcons.phone_android_round), + showTrailing: true, + onTap: () {}, + ), + ZetaMenuItem.horizontal( + label: Text('Disabled Menu Item'), + leadingIcon: Icon(ZetaIcons.home_round), + showTrailing: true, + disabled: true, + onTap: () {}, + ), + ], + ); + + static Widget get verticalExample => Wrap( + spacing: 16, + runSpacing: 16, + children: [ + ZetaMenuItem.vertical( + label: Text('Menu Item'), + icon: Icon(ZetaIcons.star_round), + onTap: () {}, + ), + ZetaMenuItem.vertical( + label: Text('Menu Item'), + icon: Icon(ZetaIcons.star_sharp), + onTap: () {}, + ), + ZetaMenuItem.vertical( + label: Text('Menu Item'), + icon: Icon(ZetaIcons.home_round), + onTap: () {}, + ), + ZetaMenuItem.vertical( + label: Text('Menu Item'), + icon: Icon(ZetaIcons.star_round), + onTap: () {}, + disabled: true, + ), + ZetaMenuItem.vertical( + label: Text('Menu Item'), + icon: Icon(ZetaIcons.star_sharp), + onTap: () {}, + disabled: true, + ), + ZetaMenuItem.vertical( + label: Text('Menu Item'), + icon: Icon(ZetaIcons.home_round), + onTap: () {}, + disabled: true, + ), + ], + ); +} diff --git a/example/widgetbook/components/menu_items_widgetbook.dart b/example/widgetbook/components/menu_items_widgetbook.dart new file mode 100644 index 00000000..0315b18d --- /dev/null +++ b/example/widgetbook/components/menu_items_widgetbook.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/menu_items.dart'; + +WidgetbookComponent menuItemsWidgetBook() { + return WidgetbookComponent( + name: 'Menu Items', + useCases: [ + WidgetbookUseCase( + name: 'Horizontal', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: MenuItemsExample.horizontalExample, + ), + ), + WidgetbookUseCase( + name: 'Vertical', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: MenuItemsExample.verticalExample, + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 10870f1b..438ec43e 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -10,6 +10,7 @@ import 'components/checkbox_widgetbook.dart'; import 'components/color_widgetbook.dart'; import 'components/grid_widgetbook.dart'; import 'components/indicator_widgetbook.dart'; +import 'components/menu_items_widgetbook.dart'; import 'components/priority_pill_widgetbook.dart'; import 'components/spacing_widgetbook.dart'; import 'components/status_label_widgetbook.dart'; @@ -42,6 +43,8 @@ class HotReload extends StatelessWidget { workcloudIndicatorWidgetBook(), avatarWidgetBook(), checkboxWidgetBook(), + buttonWidgetBook(), + menuItemsWidgetBook(), accordionWidgetBook(), buttonWidgetBook() ], diff --git a/lib/src/components/menu_items.dart b/lib/src/components/menu_items.dart new file mode 100644 index 00000000..b2a53978 --- /dev/null +++ b/lib/src/components/menu_items.dart @@ -0,0 +1,177 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '../../zeta_flutter.dart'; + +/// The type of the [ZetaMenuItem] +enum ZetaMenuItemType { + /// [ZetaMenuItem] with icon and text in a row + horizontal, + + /// [ZetaMenuItem] with icon and text in a column + vertical, +} + +/// Component [ZetaMenuItem]. +/// It can be horizontal or vertical +class ZetaMenuItem extends StatelessWidget { + /// Constructor for the component [ZetaMenuItem] + const ZetaMenuItem({ + super.key, + required this.type, + required this.label, + this.onTap, + this.leadingIcon, + this.trailingIcon, + this.showTrailing = false, + this.disabled = false, + }); + + /// Creates horizontal menu item + factory ZetaMenuItem.horizontal({ + required Widget label, + VoidCallback? onTap, + Widget? leadingIcon, + Widget? trailingIcon, + bool showTrailing = false, + bool disabled = false, + }) { + return ZetaMenuItem( + type: ZetaMenuItemType.horizontal, + label: label, + onTap: onTap, + leadingIcon: leadingIcon, + trailingIcon: trailingIcon, + showTrailing: showTrailing, + disabled: disabled, + ); + } + + /// Creates horizontal menu item + factory ZetaMenuItem.vertical({ + required Widget label, + required Widget icon, + VoidCallback? onTap, + bool disabled = false, + }) { + return ZetaMenuItem( + type: ZetaMenuItemType.vertical, + label: label, + onTap: onTap, + leadingIcon: icon, + disabled: disabled, + ); + } + + /// The type of the [ZetaMenuItem] - horizontal or vertical + final ZetaMenuItemType type; + + /// What to do when [ZetaMenuItem] is pressed. + final VoidCallback? onTap; + + /// The label of the [ZetaMenuItem] + final Widget label; + + /// The leading icon of the [ZetaMenuItem] + final Widget? leadingIcon; + + /// The trailing icon of the [ZetaMenuItem] + final Widget? trailingIcon; + + /// Determines whether to show the trailing icon. + /// Default is false. + final bool showTrailing; + + /// Sets disabled state of [ZetaMenuItem] + /// Default is false + final bool disabled; + + @override + Widget build(BuildContext context) { + final colors = Zeta.of(context).colors; + switch (type) { + case ZetaMenuItemType.horizontal: + return ConstrainedBox( + constraints: const BoxConstraints(minHeight: 48), + child: InkWell( + onTap: disabled ? null : onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + children: [ + if (leadingIcon != null) + Padding( + padding: const EdgeInsets.only(right: 10), + child: IconTheme( + data: _iconThemeData(colors, disabled, 24), + child: leadingIcon!, + ), + ), + Expanded( + child: DefaultTextStyle( + style: _defaultTextStyle(colors, disabled), + child: label, + ), + ), + ], + ), + ), + if (showTrailing || trailingIcon != null) + IconTheme( + data: _iconThemeData(colors, disabled, 24), + child: trailingIcon ?? const Icon(Icons.keyboard_arrow_right), + ), + ], + ), + ), + ), + ); + case ZetaMenuItemType.vertical: + return InkWell( + onTap: disabled ? null : onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Column( + children: [ + if (leadingIcon != null) + Padding( + padding: const EdgeInsets.only(bottom: 10), + child: IconTheme( + data: _iconThemeData(colors, disabled, 32), + child: leadingIcon!, + ), + ), + DefaultTextStyle( + style: _defaultTextStyle(colors, disabled), + child: label, + ), + ], + ), + ), + ); + } + } + + static TextStyle _defaultTextStyle(ZetaColors colors, bool disabled) => ZetaText.zetaLabelLarge.copyWith( + color: disabled ? colors.textDisabled : colors.textDefault, + height: 1, + ); + + static IconThemeData _iconThemeData(ZetaColors colors, bool disabled, double size) => IconThemeData( + color: disabled ? colors.iconDisabled : colors.iconSubtle, + size: size, + ); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', type)) + ..add(DiagnosticsProperty('disabled', disabled)) + ..add(DiagnosticsProperty('showTrailing', showTrailing)) + ..add(DiagnosticsProperty('onTap', onTap)); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index f42d8dcb..d55a9d6d 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -8,6 +8,7 @@ export 'src/components/button.dart'; export 'src/components/checkbox.dart'; export 'src/components/grid.dart'; export 'src/components/indicator.dart'; +export 'src/components/menu_items.dart'; export 'src/components/priority_pill.dart'; export 'src/components/spacing.dart'; export 'src/components/status_label.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index da9688fa..6f0d8784 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+11 +version: 0.1.1+12 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. From be7cf587995ef4a51c57fc497d91abfccf82c65b Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:31:56 +0200 Subject: [PATCH 22/41] component floating action button (#41) Co-authored-by: github-actions --- CHANGELOG.md | 34 ++- example/lib/home.dart | 10 + .../lib/pages/fab_example/fab_example.dart | 100 +++++++ .../lib/pages/fab_example/primary_fab.dart | 191 +++++++++++++ example/lib/widgets.dart | 3 + example/pubspec.lock | 2 +- example/test/fab_test.dart | 46 +++ lib/src/components/fab.dart | 264 ++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 10 files changed, 643 insertions(+), 10 deletions(-) create mode 100644 example/lib/pages/fab_example/fab_example.dart create mode 100644 example/lib/pages/fab_example/primary_fab.dart create mode 100644 example/test/fab_test.dart create mode 100644 lib/src/components/fab.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index fa78054e..489c893f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +## [0.1.1+13] - 2023-12-21 +### :flying_saucer: Other Changes +- [`51caca7`](https://github.com/zebratechnologies/zeta-flutter/commit/51caca71fce57681cabeb82e979499da9a16f4c1) - Menu Items - horizontal & vertical ([#44](https://github.com/zebratechnologies/zeta-flutter/pull/44)) + +* Menu Items - horizontal & vertical + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`8fe8750`](https://github.com/zebratechnologies/zeta-flutter/commit/8fe87502764834cdbdcc7580bddaa5def36ae518) - component floating action button ([#41](https://github.com/zebratechnologies/zeta-flutter/pull/41)) + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + ## [0.1.1+12] - 2023-12-20 ### :flying_saucer: Other Changes - [`dcafe1f`](https://github.com/zebratechnologies/zeta-flutter/commit/dcafe1f2f0436adf75e9cb36e0c4dd1bb8015def) - fix sizings and replace icons with zeta icons ([#43](https://github.com/zebratechnologies/zeta-flutter/pull/43)) @@ -11,13 +28,13 @@ Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`231fa4b`](https://github.com/zebratechnologies/zeta-flutter/commit/231fa4b860d4ecbb551ba7ec65b783d26fed43a0) - Menu Items - horizontal & vertical ([#44](https://github.com/zebratechnologies/zeta-flutter/pull/44)) -* Menu Items - horizontal & vertical - -* [automated commit] lint format and import sort - ---------- - -Co-authored-by: Atanas Yordanov +* Menu Items - horizontal & vertical + +* [automated commit] lint format and import sort + +--------- + +Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -1085,4 +1102,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+9]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+8...0.1.1+9 [0.1.1+10]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+9...0.1.1+10 [0.1.1+11]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+10...0.1.1+11 -[0.1.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+11...0.1.1+12 \ No newline at end of file +[0.1.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+11...0.1.1+12 +[0.1.1+13]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+12...0.1.1+13 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index b7250a2d..e4094572 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -11,6 +11,8 @@ import 'package:zeta_example/pages/badge_example.dart'; import 'package:zeta_example/pages/button_example.dart'; import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/checkbox_example.dart'; +import 'package:zeta_example/pages/fab_example/fab_example.dart'; +import 'package:zeta_example/pages/fab_example/primary_fab.dart'; import 'package:zeta_example/pages/grid_example.dart'; import 'package:zeta_example/pages/menu_items.dart'; import 'package:zeta_example/pages/priority_pill_example.dart'; @@ -54,6 +56,14 @@ final List components = [ Component(CheckBoxExample.name, (context) => const CheckBoxExample()), Component(AccordionExample.name, (context) => const AccordionExample()), Component(ButtonExample.name, (context) => const ButtonExample()), + Component(FABExample.name, (context) => const FABExample(), [ + Component(FabPrimarySmallCircle.name, (context) => const FabPrimarySmallCircle()), + Component(FabPrimarySmallRounded.name, (context) => const FabPrimarySmallRounded()), + Component(FabPrimarySecondSmallSharp.name, (context) => const FabPrimarySecondSmallSharp()), + Component(FabPrimarySecondLargeCircle.name, (context) => const FabPrimarySecondLargeCircle()), + Component(FabInverseLargeRounded.name, (context) => const FabInverseLargeRounded()), + Component(FabInverseLargeSharp.name, (context) => const FabInverseLargeSharp()), + ]), Component(MenuItemsExample.name, (context) => const MenuItemsExample()), ]; diff --git a/example/lib/pages/fab_example/fab_example.dart b/example/lib/pages/fab_example/fab_example.dart new file mode 100644 index 00000000..e3c79269 --- /dev/null +++ b/example/lib/pages/fab_example/fab_example.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/pages/fab_example/primary_fab.dart'; +import 'package:zeta_example/pages/button_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../home.dart'; +import '../../widgets.dart'; + +class FABExample extends StatelessWidget { + static const String name = 'FAB'; + + const FABExample({super.key}); + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + final colors = BuildExampleButtonColors(theme: theme); + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: FABExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.m), + child: getFABExampleColumn(colors), + ), + ); + }, + ); + } +} + +Widget getFABExampleColumn(BuildExampleButtonColors colors) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ZetaButton.filled( + label: 'Primary small circle', + colors: colors.primaryColors, + onPressed: () => router.pushNamed(FabPrimarySmallCircle.name), + icon: ZetaIcons.arrow_forward_round, + iconOnRight: true, + ), + ZetaButton.filled( + label: 'Primary small rounded', + colors: colors.primaryColors, + onPressed: () => router.pushNamed(FabPrimarySmallRounded.name), + icon: ZetaIcons.arrow_forward_round, + iconOnRight: true, + ), + ZetaButton.filled( + label: 'Primary second small sharp', + colors: colors.primaryVariantColors, + onPressed: () => router.pushNamed(FabPrimarySecondSmallSharp.name), + icon: ZetaIcons.arrow_forward_round, + iconOnRight: true, + ), + ZetaButton.filled( + label: 'Primary second large circle', + colors: colors.primaryVariantColors, + onPressed: () => router.pushNamed(FabPrimarySecondLargeCircle.name), + icon: ZetaIcons.arrow_forward_round, + iconOnRight: true, + ), + ZetaButton.outlined( + label: 'Inverse large rounded', + colors: colors.outlinedSubtle, + onPressed: () => router.pushNamed(FabInverseLargeRounded.name), + icon: ZetaIcons.arrow_forward_round, + iconOnRight: true, + ), + ZetaButton.outlined( + label: 'Inverse large sharp', + colors: colors.outlinedSubtle, + onPressed: () => router.pushNamed(FabInverseLargeSharp.name), + icon: ZetaIcons.arrow_forward_round, + iconOnRight: true, + ), + ], + ); + +Widget getFABScaffold( + ZetaFabShape shape, ZetaFabSize size, ZetaFabType type, ScrollController scrollController, String name) { + return ExampleScaffold( + floatingActionButton: ZetaFAB( + buttonLabel: 'Label', + scrollController: scrollController, + onPressed: () {}, + buttonShape: shape, + buttonSize: size, + buttonType: type, + ), + name: name, + child: ListView.builder( + controller: scrollController, + itemCount: 30, + itemBuilder: (context, index) => ListTile( + title: Text('Item $index'), + ), + ), + ); +} diff --git a/example/lib/pages/fab_example/primary_fab.dart b/example/lib/pages/fab_example/primary_fab.dart new file mode 100644 index 00000000..7d96d06c --- /dev/null +++ b/example/lib/pages/fab_example/primary_fab.dart @@ -0,0 +1,191 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'fab_example.dart'; + +/// Small Buttons +class FabPrimarySmallCircle extends StatefulWidget { + static const String name = 'FABPrimarySmallCircle'; + + const FabPrimarySmallCircle(); + + @override + State createState() => _FabPrimarySmallCircleState(); +} + +class _FabPrimarySmallCircleState extends State { + late ScrollController _scrollController; + + @override + void initState() { + super.initState(); + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return getFABScaffold( + ZetaFabShape.circle, ZetaFabSize.small, ZetaFabType.primary, _scrollController, FabPrimarySmallCircle.name); + } +} + +class FabPrimarySmallRounded extends StatefulWidget { + static const String name = 'FABPrimarySmallRounded'; + + const FabPrimarySmallRounded(); + + @override + State createState() => _FabPrimarySmallRoundedState(); +} + +class _FabPrimarySmallRoundedState extends State { + late ScrollController _scrollController; + + @override + void initState() { + super.initState(); + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return getFABScaffold( + ZetaFabShape.rounded, ZetaFabSize.small, ZetaFabType.primary, _scrollController, FabPrimarySmallRounded.name); + } +} + +class FabPrimarySecondSmallSharp extends StatefulWidget { + static const String name = 'FABPrimarySecondSmallSharp'; + + const FabPrimarySecondSmallSharp(); + + @override + State createState() => _FabPrimarySecondSmallSharpState(); +} + +class _FabPrimarySecondSmallSharpState extends State { + late ScrollController _scrollController; + + @override + void initState() { + super.initState(); + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return getFABScaffold(ZetaFabShape.sharp, ZetaFabSize.small, ZetaFabType.primarySecond, _scrollController, + FabPrimarySecondSmallSharp.name); + } +} + +/// Large Buttons +class FabPrimarySecondLargeCircle extends StatefulWidget { + static const String name = 'FABPrimarySecondLargeCircle'; + + const FabPrimarySecondLargeCircle(); + + @override + State createState() => _FabPrimarySecondLargeCircleState(); +} + +class _FabPrimarySecondLargeCircleState extends State { + late ScrollController _scrollController; + + @override + void initState() { + super.initState(); + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return getFABScaffold(ZetaFabShape.circle, ZetaFabSize.large, ZetaFabType.primarySecond, _scrollController, + FabPrimarySecondLargeCircle.name); + } +} + +class FabInverseLargeRounded extends StatefulWidget { + static const String name = 'FABInverseLargeRounded'; + + const FabInverseLargeRounded(); + + @override + State createState() => _FabInverseLargeRoundedState(); +} + +class _FabInverseLargeRoundedState extends State { + late ScrollController _scrollController; + + @override + void initState() { + super.initState(); + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return getFABScaffold( + ZetaFabShape.rounded, ZetaFabSize.large, ZetaFabType.inverse, _scrollController, FabInverseLargeRounded.name); + } +} + +class FabInverseLargeSharp extends StatefulWidget { + static const String name = 'FABInverseLargeSharp'; + + const FabInverseLargeSharp(); + + @override + State createState() => _FabInverseLargeSharpState(); +} + +class _FabInverseLargeSharpState extends State { + late ScrollController _scrollController; + + @override + void initState() { + super.initState(); + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return getFABScaffold( + ZetaFabShape.sharp, ZetaFabSize.large, ZetaFabType.inverse, _scrollController, FabInverseLargeSharp.name); + } +} diff --git a/example/lib/widgets.dart b/example/lib/widgets.dart index 769acbb7..9a23b6ef 100644 --- a/example/lib/widgets.dart +++ b/example/lib/widgets.dart @@ -60,11 +60,13 @@ class ExampleScaffold extends StatelessWidget { final String name; final Widget child; final List actions; + final Widget? floatingActionButton; const ExampleScaffold({ required this.name, required this.child, this.actions = const [], + this.floatingActionButton, super.key, }); @@ -74,6 +76,7 @@ class ExampleScaffold extends StatelessWidget { final colors = theme.colorScheme; return Scaffold( + floatingActionButton: floatingActionButton, appBar: AppBar( centerTitle: false, title: Text(name), diff --git a/example/pubspec.lock b/example/pubspec.lock index 357450c9..9f1a5058 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+9" + version: "0.1.1+12" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/fab_test.dart b/example/test/fab_test.dart new file mode 100644 index 00000000..d9a9311a --- /dev/null +++ b/example/test/fab_test.dart @@ -0,0 +1,46 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import 'test_components.dart'; + +void main() { + group('ZetaFAB Tests', () { + testWidgets('Initializes with correct', (WidgetTester tester) async { + final scrollController = ScrollController(); + await tester.pumpWidget(TestWidget( + widget: ZetaFAB( + scrollController: scrollController, + buttonLabel: 'Label', + ))); + + expect(find.byType(ZetaFAB), findsOneWidget); + }); + + testWidgets('OnPressed callback', (WidgetTester tester) async { + bool isPressed = false; + final scrollController = ScrollController(); + + await tester.pumpWidget(TestWidget( + widget: ZetaFAB( + scrollController: scrollController, + buttonLabel: 'Label', + onPressed: () => isPressed = true, + ))); + + await tester.tap(find.byType(ZetaFAB)); + await tester.pumpAndSettle(); + expect(isPressed, isTrue); + }); + }); + + testWidgets('Icon Test', (WidgetTester tester) async { + final scrollController = ScrollController(); + await tester.pumpWidget(TestWidget( + widget: ZetaFAB( + scrollController: scrollController, + buttonLabel: 'Label', + ))); + expect(find.byIcon(ZetaIcons.add_round), findsOneWidget); + }); +} diff --git a/lib/src/components/fab.dart b/lib/src/components/fab.dart new file mode 100644 index 00000000..71ef2c67 --- /dev/null +++ b/lib/src/components/fab.dart @@ -0,0 +1,264 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; + +import '../../zeta_flutter.dart'; + +///Defines the color of the floating action button +enum ZetaFabType { + ///[primary] + primary, + + ///[primarySecond] + primarySecond, + + ///[inverse] + inverse +} + +///Defines the shape of the floating action button +enum ZetaFabShape { + ///[circle] + circle, + + ///[rounded] + rounded, + + ///[sharp] + sharp +} + +///Defines the size of the floating action button +enum ZetaFabSize { + /// [small] 56 pixels + small, + + /// [large] 96 pixels + large, +} + +///Zeta Floating Action Button Component +class ZetaFAB extends StatefulWidget { + ///Constructs [ZetaFAB] + const ZetaFAB({ + required this.scrollController, + required this.buttonLabel, + this.buttonType = ZetaFabType.primary, + this.buttonSize = ZetaFabSize.small, + this.buttonShape = ZetaFabShape.circle, + this.buttonIcon = ZetaIcons.add_round, + this.onPressed, + this.customAnimationDuration = const Duration(milliseconds: 300), + super.key, + }); + + ///Defines the color of the button + ///Defaults to [ZetaFabType.primary] + final ZetaFabType buttonType; + + ///The Size of the button + ///Defaults to [ZetaFabSize.small] + final ZetaFabSize buttonSize; + + ///The shape for the button + ///Defaults to [ZetaFabShape.circle] + final ZetaFabShape buttonShape; + + ///Called when the button is tapped or otherwise activated. + final VoidCallback? onPressed; + + ///The [ZetaFAB] uses this controller to react to scroll change + ///and shrink/expand itself + final ScrollController scrollController; + + ///The label of the button + final String buttonLabel; + + ///Icon for the button + ///Defaults to [ZetaIcons.add_round] + final IconData buttonIcon; + + ///Animation Duration + final Duration customAnimationDuration; + + @override + State createState() => _ZetaFABState(); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('buttonType', buttonType)) + ..add(EnumProperty('buttonSize', buttonSize)) + ..add(EnumProperty('buttonShape', buttonShape)) + ..add(ObjectFlagProperty.has('onPressed', onPressed)) + ..add( + DiagnosticsProperty( + 'scrollController', + scrollController, + ), + ) + ..add(StringProperty('buttonLabel', buttonLabel)) + ..add(DiagnosticsProperty('buttonIcon', buttonIcon)) + ..add( + DiagnosticsProperty( + 'customAnimationDuration', + customAnimationDuration, + ), + ); + } +} + +class _ZetaFABState extends State { + bool _isExpanded = false; + + @override + void initState() { + super.initState(); + _isExpanded = false; + widget.scrollController.addListener(_scrollListener); + } + + void _scrollListener() { + final expanded = widget.scrollController.position.userScrollDirection == ScrollDirection.reverse; + if (_isExpanded != expanded) { + setState(() => _isExpanded = expanded); + } + } + + @override + void dispose() { + widget.scrollController.removeListener(_scrollListener); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + final colors = _FabButtonColors.fromButtonType(widget.buttonType, theme); + final textStyle = _getTextStyle(); + final buttonSize = _getButtonSize(); + final iconSize = _getIconSize(); + return ElevatedButton( + onPressed: widget.onPressed, + style: _buttonStyle(colors), + child: AnimatedSwitcher( + duration: widget.customAnimationDuration, + child: _isExpanded ? _buildFABExtended(buttonSize, iconSize, textStyle) : _buildFAB(buttonSize, iconSize), + ), + ); + } + + Widget _buildFAB(double buttonSize, double iconSize) { + return SizedBox( + width: buttonSize, + height: buttonSize, + child: Icon(widget.buttonIcon, size: iconSize), + ); + } + + Widget _buildFABExtended( + double buttonSize, + double iconSize, + TextStyle textStyle, + ) { + return Padding( + padding: _getPadding(), + child: SizedBox( + height: buttonSize, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(widget.buttonIcon, size: iconSize), + const SizedBox(width: Dimensions.x2), + Text(widget.buttonLabel, style: textStyle), + ], + ), + ), + ); + } + + ButtonStyle _buttonStyle(_FabButtonColors colors) { + return ElevatedButton.styleFrom( + padding: EdgeInsets.zero, + shape: _getButtonShape(), + backgroundColor: colors.backgroundColor, + foregroundColor: colors.foregroundColor, + ).copyWith( + overlayColor: MaterialStateProperty.resolveWith((Set states) { + if (states.contains(MaterialState.pressed)) return colors.actionColor; + return null; + }), + ); + } + + OutlinedBorder _getButtonShape() { + if (widget.buttonShape == ZetaFabShape.circle && !_isExpanded) { + return const CircleBorder(); + } + return RoundedRectangleBorder( + borderRadius: _isExpanded ? _getBorderRadiusExtended() : _getBorderRadius(), + ); + } + + BorderRadius _getBorderRadius() => widget.buttonShape == ZetaFabShape.rounded + ? BorderRadius.circular( + widget.buttonSize == ZetaFabSize.small ? Dimensions.x2 : Dimensions.x4, + ) + : BorderRadius.zero; + + BorderRadius _getBorderRadiusExtended() => widget.buttonShape == ZetaFabShape.circle + ? BorderRadius.circular( + widget.buttonSize == ZetaFabSize.small ? Dimensions.x7 : Dimensions.x12, + ) + : widget.buttonShape == ZetaFabShape.rounded + ? BorderRadius.circular(Dimensions.x2) + : BorderRadius.zero; + + TextStyle _getTextStyle() => + widget.buttonSize == ZetaFabSize.large ? ZetaText.zetaTitleLarge : ZetaText.zetaTitleMedium; + + double _getButtonSize() => widget.buttonSize == ZetaFabSize.small ? Dimensions.x14 : Dimensions.x24; + + double _getIconSize() => widget.buttonSize == ZetaFabSize.small ? Dimensions.x6 : Dimensions.x9; + + EdgeInsets _getPadding() => !_isExpanded + ? EdgeInsets.zero + : widget.buttonShape == ZetaFabShape.circle + ? const EdgeInsets.only(right: 20, left: 20) + : const EdgeInsets.only(right: 18, left: 18); +} + +///Defines colors for FAB Components +class _FabButtonColors extends ZetaWidgetColor { + const _FabButtonColors({ + required this.actionColor, + required super.backgroundColor, + required super.foregroundColor, + }); + + factory _FabButtonColors.fromButtonType(ZetaFabType buttonType, Zeta theme) { + switch (buttonType) { + case ZetaFabType.primary: + return _FabButtonColors( + backgroundColor: theme.colors.blue.shade60, + foregroundColor: theme.colors.white, + actionColor: theme.colors.blue.shade80, + ); + case ZetaFabType.primarySecond: + return _FabButtonColors( + backgroundColor: theme.colors.yellow.lighten(16), + foregroundColor: theme.colors.black, + actionColor: theme.colors.yellow, + ); + case ZetaFabType.inverse: + return _FabButtonColors( + backgroundColor: theme.colors.iconDefault, + foregroundColor: theme.colors.iconInverse, + actionColor: theme.colors.iconSubtle, + ); + } + } + + final Color actionColor; +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index d55a9d6d..f7d2f338 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -6,6 +6,7 @@ export 'src/components/avatar.dart'; export 'src/components/badge.dart'; export 'src/components/button.dart'; export 'src/components/checkbox.dart'; +export 'src/components/fab.dart'; export 'src/components/grid.dart'; export 'src/components/indicator.dart'; export 'src/components/menu_items.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 6f0d8784..017c60e6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+12 +version: 0.1.1+13 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. From 36b980896602320114c845b68a99a1c4c2e03ecb Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:34:16 +0200 Subject: [PATCH 23/41] Page banner (#40) Co-authored-by: github-actions --- CHANGELOG.md | 13 +- example/lib/home.dart | 2 + example/lib/pages/in_page_banner_example.dart | 121 ++++++++ example/test/in_page_banner_test.dart | 81 +++++ .../components/in_page_banner_widgetbook.dart | 124 ++++++++ example/widgetbook/widgetbook.dart | 2 + lib/src/components/in_page_banner.dart | 293 ++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 9 files changed, 637 insertions(+), 2 deletions(-) create mode 100644 example/lib/pages/in_page_banner_example.dart create mode 100644 example/test/in_page_banner_test.dart create mode 100644 example/widgetbook/components/in_page_banner_widgetbook.dart create mode 100644 lib/src/components/in_page_banner.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 489c893f..56278c44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [0.1.1+14] - 2023-12-21 +### :flying_saucer: Other Changes +- [`be7cf58`](https://github.com/zebratechnologies/zeta-flutter/commit/be7cf587995ef4a51c57fc497d91abfccf82c65b) - component floating action button ([#41](https://github.com/zebratechnologies/zeta-flutter/pull/41)) + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`a5d7181`](https://github.com/zebratechnologies/zeta-flutter/commit/a5d71816ff9d6aa9426cda38ee9d6f1116a36496) - Page banner ([#40](https://github.com/zebratechnologies/zeta-flutter/pull/40)) + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + ## [0.1.1+13] - 2023-12-21 ### :flying_saucer: Other Changes - [`51caca7`](https://github.com/zebratechnologies/zeta-flutter/commit/51caca71fce57681cabeb82e979499da9a16f4c1) - Menu Items - horizontal & vertical ([#44](https://github.com/zebratechnologies/zeta-flutter/pull/44)) @@ -1103,4 +1113,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+10]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+9...0.1.1+10 [0.1.1+11]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+10...0.1.1+11 [0.1.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+11...0.1.1+12 -[0.1.1+13]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+12...0.1.1+13 \ No newline at end of file +[0.1.1+13]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+12...0.1.1+13 +[0.1.1+14]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+13...0.1.1+14 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index e4094572..d51808ac 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -14,6 +14,7 @@ import 'package:zeta_example/pages/checkbox_example.dart'; import 'package:zeta_example/pages/fab_example/fab_example.dart'; import 'package:zeta_example/pages/fab_example/primary_fab.dart'; import 'package:zeta_example/pages/grid_example.dart'; +import 'package:zeta_example/pages/in_page_banner_example.dart'; import 'package:zeta_example/pages/menu_items.dart'; import 'package:zeta_example/pages/priority_pill_example.dart'; import 'package:zeta_example/pages/icons_example.dart'; @@ -54,6 +55,7 @@ final List components = [ Component(NegativeAppBarExample.name, (context) => const NegativeAppBarExample()), ]), Component(CheckBoxExample.name, (context) => const CheckBoxExample()), + Component(InPageBannerExample.name, (context) => const InPageBannerExample()), Component(AccordionExample.name, (context) => const AccordionExample()), Component(ButtonExample.name, (context) => const ButtonExample()), Component(FABExample.name, (context) => const FABExample(), [ diff --git a/example/lib/pages/in_page_banner_example.dart b/example/lib/pages/in_page_banner_example.dart new file mode 100644 index 00000000..ad297f59 --- /dev/null +++ b/example/lib/pages/in_page_banner_example.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class InPageBannerExample extends StatelessWidget { + static const String name = 'InPageBanner'; + + const InPageBannerExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: InPageBannerExample.name, + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _getTitle('Default Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.neutral), + _getTitle('Info Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.info), + _getTitle('Positive Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.positive), + _getTitle('Warning Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.warning), + _getTitle('Negative Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.negative), + _getTitle('Custom Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.custom, + customColors: ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue)), + Divider( + height: 50, + color: Colors.transparent, + ), + _getTitle('Default Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.neutral, border: BorderType.sharp), + _getTitle('Info Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.info, border: BorderType.sharp), + _getTitle('Positive Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.positive, border: BorderType.sharp), + _getTitle('Warning Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.warning, border: BorderType.sharp), + _getTitle('Negative Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.negative, border: BorderType.sharp), + _getTitle('Custom Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.custom, + border: BorderType.sharp, + customColors: ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue)), + ], + ), + ), + ), + ); + } + + Widget _getTitle(String title) => Container( + height: 50, + child: Center(child: Text(title, style: ZetaText.zetaTitleLarge)), + ); +} + +const _content = 'Lorem ipsum dolor sit amet, conse ctetur cididunt ut' + 'labore et do lore magna aliqua.'; + +ZetaInPageBanner _getExampleBanner( + WidgetSeverity severity, + BorderType type, { + String? title, + bool showCloseBtn = true, + bool showFirstButton = false, + bool showSecondButton = false, + ZetaWidgetColor? customColors, + IconData? customIcon, +}) => + ZetaInPageBanner( + content: Text(_content), + onClose: () {}, + borderType: type, + severity: severity, + showIconClose: showCloseBtn, + title: title, + firstButton: showFirstButton ? ZetaPageBannerButton(label: 'Button', onPressed: () {}) : null, + secondButton: showSecondButton ? ZetaPageBannerButton(label: 'Button', onPressed: () {}) : null, + customColors: customColors, + customIcon: customIcon); + +Column buildExampleBannerColumn(WidgetSeverity severity, + {ZetaWidgetColor? customColors, BorderType border = BorderType.rounded, IconData? customIcon}) { + const _title = 'Banner Title'; + return Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + mainAxisSize: MainAxisSize.min, + children: [ + _getExampleBanner(severity, border, + title: _title, + showFirstButton: true, + showSecondButton: true, + customColors: customColors, + customIcon: customIcon), + //Rounded (Icon + Title + Close + Buttons) + Divider(color: Colors.transparent), + _getExampleBanner(severity, border, title: _title, customColors: customColors, customIcon: customIcon), + //Rounded (Icon + Title + Close ) + Divider(color: Colors.transparent), + _getExampleBanner(severity, border, customColors: customColors, customIcon: customIcon), + //Rounded (Icon + Close) + Divider(color: Colors.transparent), + _getExampleBanner(severity, border, + showCloseBtn: false, title: _title, customColors: customColors, customIcon: customIcon), + //Rounded (Icon + Title) + Divider(color: Colors.transparent), + _getExampleBanner(severity, border, showCloseBtn: false, customColors: customColors, customIcon: customIcon), + //Rounded (Icon) + Divider(), + //Rounded (Icon + Title + Close) + ], + ); +} diff --git a/example/test/in_page_banner_test.dart b/example/test/in_page_banner_test.dart new file mode 100644 index 00000000..0716b13e --- /dev/null +++ b/example/test/in_page_banner_test.dart @@ -0,0 +1,81 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; +import 'package:flutter/material.dart'; + +import 'test_components.dart'; + +void main() { + group('ZetaInPageBanner Tests', () { + testWidgets('ZetaInPageBanner creation', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaInPageBanner( + content: Text('Test'), + )), + ); + + expect(find.byType(ZetaInPageBanner), findsOneWidget); + }); + }); + + testWidgets('ZetaInPageBanner displays content text', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaInPageBanner( + content: Text('Test'), + )), + ); + + expect(find.text('Test'), findsOneWidget); + }); + + testWidgets('ZetaInPageBanner shows/hides \'close icon\' correctly', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaInPageBanner( + content: Text('Test'), + showIconClose: true, + )), + ); + expect(find.byIcon(ZetaIcons.close_round), findsOneWidget); + + await tester.pumpWidget( + TestWidget( + widget: ZetaInPageBanner( + content: Text('Test'), + showIconClose: false, + )), + ); + expect(find.byIcon(ZetaIcons.close_sharp), findsNothing); + }); + + testWidgets('ZetaInPageBanner button callbacks work', (WidgetTester tester) async { + bool onPressed = false; + await tester.pumpWidget( + TestWidget( + widget: ZetaInPageBanner( + content: Text('Test'), + firstButton: ZetaPageBannerButton(label: 'Test Button', onPressed: () => onPressed = true), + )), + ); + + await tester.tap(find.text('Test Button')); + await tester.pumpAndSettle(); + expect(onPressed, isTrue); + }); + + testWidgets('ZetaInPageBanner \'close\' icon tap test', (WidgetTester tester) async { + bool closeIconIsTapped = false; + await tester.pumpWidget( + TestWidget( + widget: ZetaInPageBanner( + onClose: () => closeIconIsTapped = true, + content: Text('Test'), + )), + ); + final closeIcon = find.byIcon(ZetaIcons.close_round); + await tester.tap(closeIcon); + await tester.pump(); + expect(closeIconIsTapped, isTrue); + }); +} diff --git a/example/widgetbook/components/in_page_banner_widgetbook.dart b/example/widgetbook/components/in_page_banner_widgetbook.dart new file mode 100644 index 00000000..01e4dab4 --- /dev/null +++ b/example/widgetbook/components/in_page_banner_widgetbook.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/in_page_banner_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent inPageBannerWidgetBook() { + Widget _getTitle(String title) => Container( + height: 50, + child: Center(child: Text(title, style: ZetaText.zetaTitleLarge)), + ); + + ZetaWidgetColor _getCustomColors() => + ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue); + + return WidgetbookComponent( + name: 'InPageBanner', + useCases: [ + WidgetbookUseCase( + name: 'Default In Page Banner', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _getTitle('Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.neutral), + _getTitle('Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.neutral, border: BorderType.sharp), + ], + ), + ), + ), + ), + WidgetbookUseCase( + name: 'Info In Page Banner', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _getTitle('Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.info), + _getTitle('Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.info, border: BorderType.sharp), + ], + ), + ), + ), + ), + WidgetbookUseCase( + name: 'Positive In Page Banner', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _getTitle('Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.positive), + _getTitle('Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.positive, border: BorderType.sharp), + ], + ), + ), + ), + ), + WidgetbookUseCase( + name: 'Warning In Page Banner', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _getTitle('Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.warning), + _getTitle('Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.warning, border: BorderType.sharp), + ], + ), + ), + ), + ), + WidgetbookUseCase( + name: 'Negative In Page Banner', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _getTitle('Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.negative), + _getTitle('Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.negative, border: BorderType.sharp), + ], + ), + ), + ), + ), + WidgetbookUseCase( + name: 'Custom In Page Banner', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _getTitle('Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.custom, + customColors: _getCustomColors(), customIcon: ZetaIcons.alert_round), + _getTitle('Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.custom, + customColors: _getCustomColors(), border: BorderType.sharp, customIcon: ZetaIcons.alert_sharp), + ], + ), + ), + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 438ec43e..73cf6507 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -9,6 +9,7 @@ import 'components/button_widgetbook.dart'; import 'components/checkbox_widgetbook.dart'; import 'components/color_widgetbook.dart'; import 'components/grid_widgetbook.dart'; +import 'components/in_page_banner_widgetbook.dart'; import 'components/indicator_widgetbook.dart'; import 'components/menu_items_widgetbook.dart'; import 'components/priority_pill_widgetbook.dart'; @@ -44,6 +45,7 @@ class HotReload extends StatelessWidget { avatarWidgetBook(), checkboxWidgetBook(), buttonWidgetBook(), + inPageBannerWidgetBook(), menuItemsWidgetBook(), accordionWidgetBook(), buttonWidgetBook() diff --git a/lib/src/components/in_page_banner.dart b/lib/src/components/in_page_banner.dart new file mode 100644 index 00000000..f5e9af7b --- /dev/null +++ b/lib/src/components/in_page_banner.dart @@ -0,0 +1,293 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; + +///[ZetaInPageBanner] button attributes +class ZetaPageBannerButton { + ///Constructs [ZetaPageBannerButton] + const ZetaPageBannerButton({this.onPressed, this.label}); + + ///Called when the button is tapped. + final VoidCallback? onPressed; + + ///Label for the button + final String? label; +} + +///Zeta In Page Banner +class ZetaInPageBanner extends StatelessWidget { + ///Constructs [ZetaInPageBanner] + const ZetaInPageBanner({ + required this.content, + this.borderType = BorderType.rounded, + this.severity = WidgetSeverity.info, + this.showIconClose = true, + this.onClose, + this.title, + this.customColors, + this.customIcon, + this.firstButton, + this.secondButton, + super.key, + }); + + ///The content of the banner + final Widget content; + + ///The border type of the banner + ///Defaults to 'rounded' + final BorderType borderType; + + ///Determines the color of the banner + ///Defaults to 'neutral' + final WidgetSeverity severity; + + ///Determines if the banner hase icon for closing + ///Defaults to true + final bool showIconClose; + + ///Title of the banner + final String? title; + + ///If [severity] is set to 'custom', + /// + ///[customColors] should be set. + final ZetaWidgetColor? customColors; + + ///Custom icon + final IconData? customIcon; + + ///Attributes for the left button + final ZetaPageBannerButton? firstButton; + + ///Attributes for the right button + final ZetaPageBannerButton? secondButton; + + ///Called when the button 'Close' is tapped. + final VoidCallback? onClose; + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + final colors = _getColors(theme); + return DecoratedBox( + decoration: _buildDecoration(colors), + child: Padding( + padding: const EdgeInsets.all(Dimensions.x3), + child: Column( + children: _buildBannerContent(theme, colors), + ), + ), + ); + } + + List _buildBannerContent(Zeta theme, ZetaWidgetColor colors) { + final hasTitle = title != null; + return [ + if (hasTitle) _buildTitleRow(colors, theme), + _buildContentRow(theme, colors, hasTitle), + ]; + } + + Widget _buildTitleRow(ZetaWidgetColor colors, Zeta theme) { + return Padding( + padding: const EdgeInsets.only(bottom: Dimensions.x2), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + _buildIconLeft(colors, theme), + const SizedBox(width: Dimensions.x2), + if (title != null) ...[_buildTitle()], + ], + ), + ), + if (showIconClose) ...[ + Align( + alignment: Alignment.centerRight, + child: _buildIconClose(), + ), + ], + ], + ), + ); + } + + Widget _buildContentRow(Zeta theme, ZetaWidgetColor colors, bool hasTitle) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (title == null) ...[ + _buildIconLeft(colors, theme), + const SizedBox(width: Dimensions.x2), + ], + _buildContent(hasTitle, theme), + if (showIconClose && !hasTitle) ...[_buildIconClose()], + ], + ), + _buildButtonsRow(theme, colors), + ], + ); + } + + Widget _buildButtonsRow(Zeta theme, ZetaWidgetColor colors) { + return Row( + children: [ + const Padding(padding: EdgeInsets.only(left: Dimensions.x7)), + if (firstButton != null) ...[ + _buildButton(theme, colors, firstButton!), + const SizedBox(width: Dimensions.x2), + ], + if (secondButton != null) ...[ + _buildButton(theme, colors, secondButton!), + ], + ], + ); + } + + BoxDecoration _buildDecoration(ZetaWidgetColor colors) { + return BoxDecoration( + color: colors.backgroundColor, + border: Border.all(color: colors.foregroundColor), + borderRadius: BorderRadius.circular( + borderType == BorderType.rounded ? Dimensions.x1 : Dimensions.x0, + ), + ); + } + + Expanded _buildContent(bool hasTitle, Zeta theme) => Expanded( + child: Padding( + padding: EdgeInsets.only(left: hasTitle ? Dimensions.x7 : Dimensions.x0), + child: DefaultTextStyle( + style: ZetaText.zetaBodySmall.apply(color: theme.colors.textDefault), + child: content, + ), + ), + ); + + Widget _buildIconClose() => GestureDetector( + onTap: onClose, + child: Icon( + borderType == BorderType.sharp ? ZetaIcons.close_sharp : ZetaIcons.close_round, + size: Dimensions.x5, + ), + ); + + Icon _buildIconLeft(ZetaWidgetColor colors, Zeta theme) => Icon( + _getIconLeft(), + size: Dimensions.x5, + color: severity == WidgetSeverity.neutral ? theme.colors.textDefault : colors.foregroundColor, + ); + + Widget _buildTitle() => Flexible( + child: Text( + title!, + style: ZetaText.zetaTitleMedium, + softWrap: true, + overflow: TextOverflow.ellipsis, + ), + ); + + Widget _buildButton( + Zeta theme, + ZetaWidgetColor colors, + ZetaPageBannerButton buttonAttributes, + ) { + return Padding( + padding: const EdgeInsets.only(top: Dimensions.x3), + child: ZetaButton.outlined( + label: buttonAttributes.label ?? '', + borderType: borderType, + size: ZetaWidgetSize.medium, + colors: ZetaButtonColors( + borderColor: theme.colors.borderSubtle, + foregroundColor: theme.colors.textDefault, + actionColor: ZetaColorBase.greyCool.shade30, + ), + onPressed: buttonAttributes.onPressed, + ), + ); + } + + IconData _getIconLeft() { + final isRounded = borderType == BorderType.rounded; + final defaultIcon = isRounded ? ZetaIcons.info_round : ZetaIcons.info_sharp; + if (severity == WidgetSeverity.positive) { + return isRounded ? ZetaIcons.check_circle_round : ZetaIcons.check_circle_sharp; + } else if (severity == WidgetSeverity.warning) { + return isRounded ? ZetaIcons.warning_round : ZetaIcons.warning_sharp; + } else if (severity == WidgetSeverity.negative) { + return isRounded ? ZetaIcons.error_round : ZetaIcons.error_sharp; + } else if (severity == WidgetSeverity.custom) { + return customIcon ?? defaultIcon; + } + return defaultIcon; + } + + ZetaWidgetColor _getColors(Zeta theme) { + final defaultColorScheme = ZetaWidgetColor( + backgroundColor: theme.colors.surfacePrimary, + foregroundColor: theme.colors.borderDefault, + ); + switch (severity) { + case WidgetSeverity.neutral: + return defaultColorScheme; + case WidgetSeverity.info: + return ZetaWidgetColor( + backgroundColor: theme.colors.info.surface, + foregroundColor: theme.colors.info.border, + ); + case WidgetSeverity.positive: + return ZetaWidgetColor( + backgroundColor: theme.colors.positive.surface, + foregroundColor: theme.colors.positive.border, + ); + case WidgetSeverity.warning: + return ZetaWidgetColor( + backgroundColor: theme.colors.warning.surface.lighten(6), + foregroundColor: theme.colors.warning.border, + ); + case WidgetSeverity.negative: + return ZetaWidgetColor( + backgroundColor: theme.colors.negative.surface, + foregroundColor: theme.colors.negative.border, + ); + case WidgetSeverity.custom: + return customColors ?? defaultColorScheme; + } + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('borderType', borderType)) + ..add(EnumProperty('severity', severity)) + ..add(DiagnosticsProperty('isClosing', showIconClose)) + ..add(StringProperty('title', title)) + ..add( + DiagnosticsProperty('customColors', customColors), + ) + ..add(DiagnosticsProperty('customIcon', customIcon)) + ..add( + DiagnosticsProperty('firstButton', firstButton), + ) + ..add( + DiagnosticsProperty( + 'secondButton', + secondButton, + ), + ) + ..add( + ObjectFlagProperty.has( + 'onCloseFunction', + onClose, + ), + ); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index f7d2f338..0979c590 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -8,6 +8,7 @@ export 'src/components/button.dart'; export 'src/components/checkbox.dart'; export 'src/components/fab.dart'; export 'src/components/grid.dart'; +export 'src/components/in_page_banner.dart'; export 'src/components/indicator.dart'; export 'src/components/menu_items.dart'; export 'src/components/priority_pill.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 017c60e6..09601c9f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+13 +version: 0.1.1+14 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. From 225a059aa191f595db4982960c854c2e94c5bdc4 Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Tue, 2 Jan 2024 10:07:16 +0200 Subject: [PATCH 24/41] create bottom sheet (#45) Co-authored-by: Atanas Yordanov Co-authored-by: github-actions --- CHANGELOG.md | 14 ++- example/lib/home.dart | 2 + example/lib/pages/bottom_sheet.dart | 58 ++++++++++++ .../components/bottom_sheet_widgetbook.dart | 25 ++++++ example/widgetbook/widgetbook.dart | 4 +- lib/src/components/bottom_sheet.dart | 90 +++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 8 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 example/lib/pages/bottom_sheet.dart create mode 100644 example/widgetbook/components/bottom_sheet_widgetbook.dart create mode 100644 lib/src/components/bottom_sheet.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 56278c44..bdb8b6ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [0.1.1+15] - 2024-01-02 +### :flying_saucer: Other Changes +- [`36b9808`](https://github.com/zebratechnologies/zeta-flutter/commit/36b980896602320114c845b68a99a1c4c2e03ecb) - Page banner ([#40](https://github.com/zebratechnologies/zeta-flutter/pull/40)) + +Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`03f2ed7`](https://github.com/zebratechnologies/zeta-flutter/commit/03f2ed7fb7f34dd995cb850f67582b76a2132111) - create bottom sheet ([#45](https://github.com/zebratechnologies/zeta-flutter/pull/45)) + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* + + ## [0.1.1+14] - 2023-12-21 ### :flying_saucer: Other Changes - [`be7cf58`](https://github.com/zebratechnologies/zeta-flutter/commit/be7cf587995ef4a51c57fc497d91abfccf82c65b) - component floating action button ([#41](https://github.com/zebratechnologies/zeta-flutter/pull/41)) @@ -1114,4 +1125,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+11]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+10...0.1.1+11 [0.1.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+11...0.1.1+12 [0.1.1+13]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+12...0.1.1+13 -[0.1.1+14]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+13...0.1.1+14 \ No newline at end of file +[0.1.1+14]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+13...0.1.1+14 +[0.1.1+15]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+14...0.1.1+15 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index d51808ac..047b2e81 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -8,6 +8,7 @@ import 'package:zeta_example/pages/app_bar_example/positive_app_bar.dart'; import 'package:zeta_example/pages/app_bar_example/warning_app_bar.dart'; import 'package:zeta_example/pages/avatar_example.dart'; import 'package:zeta_example/pages/badge_example.dart'; +import 'package:zeta_example/pages/bottom_sheet.dart'; import 'package:zeta_example/pages/button_example.dart'; import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/checkbox_example.dart'; @@ -67,6 +68,7 @@ final List components = [ Component(FabInverseLargeSharp.name, (context) => const FabInverseLargeSharp()), ]), Component(MenuItemsExample.name, (context) => const MenuItemsExample()), + Component(BottomSheetExample.name, (context) => const BottomSheetExample()), ]; class Home extends StatefulWidget { diff --git a/example/lib/pages/bottom_sheet.dart b/example/lib/pages/bottom_sheet.dart new file mode 100644 index 00000000..8df661db --- /dev/null +++ b/example/lib/pages/bottom_sheet.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class BottomSheetExample extends StatelessWidget { + static const String name = 'BottomSheet'; + + const BottomSheetExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: BottomSheetExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + bottomSheet(context), + bottomSheet(context, Alignment.centerLeft), + ], + ), + ), + ); + }, + ); + } + + static bottomSheet(BuildContext context, [AlignmentGeometry? alignment]) => ZetaMenuItem.horizontal( + label: Text('Bottom Sheet - ${alignment ?? Alignment.center}'), + trailingIcon: Icon(ZetaIcons.caret_down_round), + onTap: () { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return ZetaBottomSheet( + title: 'Bottom Sheet', + titleAlignment: alignment, + body: Wrap( + spacing: 12, + runSpacing: 12, + children: List.generate( + 6, + (index) => ZetaMenuItem.vertical( + label: Text('Menu Item'), + icon: Icon(ZetaIcons.star_round), + onTap: () {}, + ), + ), + ), + ); + }, + ); + }, + ); +} diff --git a/example/widgetbook/components/bottom_sheet_widgetbook.dart b/example/widgetbook/components/bottom_sheet_widgetbook.dart new file mode 100644 index 00000000..93c11a8b --- /dev/null +++ b/example/widgetbook/components/bottom_sheet_widgetbook.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/bottom_sheet.dart'; + +WidgetbookComponent bottomSheetWidgetBook() { + return WidgetbookComponent( + name: 'Bottom Sheet', + useCases: [ + WidgetbookUseCase( + name: 'Centered title', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: BottomSheetExample.bottomSheet(context), + ), + ), + WidgetbookUseCase( + name: 'Title aligned left', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: BottomSheetExample.bottomSheet(context, Alignment.centerLeft), + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 73cf6507..e27428d3 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -5,6 +5,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; import 'components/accordion_widgetbook.dart'; import 'components/avatar_widgetbook.dart'; import 'components/badge_widgetbook.dart'; +import 'components/bottom_sheet_widgetbook.dart'; import 'components/button_widgetbook.dart'; import 'components/checkbox_widgetbook.dart'; import 'components/color_widgetbook.dart'; @@ -48,7 +49,8 @@ class HotReload extends StatelessWidget { inPageBannerWidgetBook(), menuItemsWidgetBook(), accordionWidgetBook(), - buttonWidgetBook() + buttonWidgetBook(), + bottomSheetWidgetBook(), ], ), ], diff --git a/lib/src/components/bottom_sheet.dart b/lib/src/components/bottom_sheet.dart new file mode 100644 index 00000000..e57adb04 --- /dev/null +++ b/lib/src/components/bottom_sheet.dart @@ -0,0 +1,90 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; + +/// Component [ZetaBottomSheet] +class ZetaBottomSheet extends StatelessWidget { + /// Constructor for [ZetaBottomSheet]. + const ZetaBottomSheet({ + super.key, + this.title, + this.titleAlignment, + this.body, + this.horizontalAlignment, + }); + + /// The title of [ZetaBottomSheet]. + final String? title; + + /// The alignment of the title. + /// Default is `Alignment.center` + final AlignmentGeometry? titleAlignment; + + /// The content of [ZetaBottomSheet]. + final Widget? body; + + /// The horizontal alignment of the [ZetaBottomSheet]'s content. + final CrossAxisAlignment? horizontalAlignment; + + @override + Widget build(BuildContext context) { + final colors = Zeta.of(context).colors; + final themeMode = Zeta.of(context).themeMode; + final isDark = themeMode == ThemeMode.dark || + (themeMode == ThemeMode.system && PlatformDispatcher.instance.platformBrightness == Brightness.dark); + + return Container( + width: double.infinity, + padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), + decoration: BoxDecoration( + color: isDark ? colors.cool.shade20 : colors.surfacePrimary, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: horizontalAlignment ?? CrossAxisAlignment.center, + children: [ + Align( + child: SizedBox( + height: 36, + child: Padding( + padding: const EdgeInsets.only(top: 8), + child: Icon( + Icons.maximize_rounded, + size: 60, + color: colors.surfaceDisabled, + ), + ), + ), + ), + if (title != null) + Align( + alignment: titleAlignment ?? Alignment.center, + child: Text( + title!, + style: ZetaText.zetaTitleLarge.copyWith( + color: colors.textDefault, + fontSize: 18, + height: 1.33, + ), + ), + ), + body ?? const SizedBox(), + ], + ), + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('title', title)) + ..add(DiagnosticsProperty('titleAlignment', titleAlignment)) + ..add(EnumProperty('horizontalAlignment', horizontalAlignment)); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 0979c590..5c20ebdc 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -4,6 +4,7 @@ library zeta_flutter; export 'src/components/accordion.dart'; export 'src/components/avatar.dart'; export 'src/components/badge.dart'; +export 'src/components/bottom_sheet.dart'; export 'src/components/button.dart'; export 'src/components/checkbox.dart'; export 'src/components/fab.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 09601c9f..e540da0d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+14 +version: 0.1.1+15 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. From 500013d71690410de469b5939a9b6aba6d4d5882 Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:14:51 +0200 Subject: [PATCH 25/41] Password input (#47) Co-authored-by: github-actions Co-authored-by: Atanas Yordanov --- CHANGELOG.md | 17 +- example/lib/home.dart | 2 + example/lib/pages/password_input_example.dart | 85 +++++ example/pubspec.lock | 2 +- example/test/password_input_test.dart | 54 +++ .../components/password_input_widgetbook.dart | 50 +++ example/widgetbook/widgetbook.dart | 2 + lib/src/components/password_input.dart | 311 ++++++++++++++++++ lib/zeta_flutter.dart | 1 + pubspec.yaml | 2 +- 10 files changed, 522 insertions(+), 4 deletions(-) create mode 100644 example/lib/pages/password_input_example.dart create mode 100644 example/test/password_input_test.dart create mode 100644 example/widgetbook/components/password_input_widgetbook.dart create mode 100644 lib/src/components/password_input.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index bdb8b6ba..6803a8c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [0.1.1+16] - 2024-01-02 +### :flying_saucer: Other Changes +- [`225a059`](https://github.com/zebratechnologies/zeta-flutter/commit/225a059aa191f595db4982960c854c2e94c5bdc4) - create bottom sheet ([#45](https://github.com/zebratechnologies/zeta-flutter/pull/45)) + +Co-authored-by: Atanas Yordanov +Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +- [`656ca24`](https://github.com/zebratechnologies/zeta-flutter/commit/656ca2470112a171064f0d2d7477bf087a4f98bd) - Password input ([#47](https://github.com/zebratechnologies/zeta-flutter/pull/47)) + +Co-authored-by: github-actions +Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* + + ## [0.1.1+15] - 2024-01-02 ### :flying_saucer: Other Changes - [`36b9808`](https://github.com/zebratechnologies/zeta-flutter/commit/36b980896602320114c845b68a99a1c4c2e03ecb) - Page banner ([#40](https://github.com/zebratechnologies/zeta-flutter/pull/40)) @@ -5,7 +17,7 @@ Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`03f2ed7`](https://github.com/zebratechnologies/zeta-flutter/commit/03f2ed7fb7f34dd995cb850f67582b76a2132111) - create bottom sheet ([#45](https://github.com/zebratechnologies/zeta-flutter/pull/45)) -Co-authored-by: Atanas Yordanov +Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* @@ -1126,4 +1138,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+12]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+11...0.1.1+12 [0.1.1+13]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+12...0.1.1+13 [0.1.1+14]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+13...0.1.1+14 -[0.1.1+15]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+14...0.1.1+15 \ No newline at end of file +[0.1.1+15]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+14...0.1.1+15 +[0.1.1+16]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+15...0.1.1+16 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 047b2e81..6b728175 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -17,6 +17,7 @@ import 'package:zeta_example/pages/fab_example/primary_fab.dart'; import 'package:zeta_example/pages/grid_example.dart'; import 'package:zeta_example/pages/in_page_banner_example.dart'; import 'package:zeta_example/pages/menu_items.dart'; +import 'package:zeta_example/pages/password_input_example.dart'; import 'package:zeta_example/pages/priority_pill_example.dart'; import 'package:zeta_example/pages/icons_example.dart'; import 'package:zeta_example/pages/indicator_example.dart'; @@ -68,6 +69,7 @@ final List components = [ Component(FabInverseLargeSharp.name, (context) => const FabInverseLargeSharp()), ]), Component(MenuItemsExample.name, (context) => const MenuItemsExample()), + Component(PasswordInputExample.name, (context) => const PasswordInputExample()), Component(BottomSheetExample.name, (context) => const BottomSheetExample()), ]; diff --git a/example/lib/pages/password_input_example.dart b/example/lib/pages/password_input_example.dart new file mode 100644 index 00000000..9ba9e9e1 --- /dev/null +++ b/example/lib/pages/password_input_example.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class PasswordInputExample extends StatefulWidget { + static const String name = 'PasswordInput'; + + const PasswordInputExample({Key? key}) : super(key: key); + + @override + State createState() => _PasswordInputExampleState(); +} + +class _PasswordInputExampleState extends State { + final _passwordController = TextEditingController(); + final _formKey = GlobalKey(); + + @override + void dispose() { + _passwordController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Form( + key: _formKey, + child: ExampleScaffold( + name: PasswordInputExample.name, + child: Padding( + padding: EdgeInsets.all(10), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding(padding: EdgeInsets.only(top: 20)), + ZetaPasswordInput( + size: ZetaWidgetSize.medium, + borderType: BorderType.sharp, + footerText: 'Error state is triggered if the password contains digits', + footerIcon: ZetaIcons.info_round, + hintText: 'Password', + controller: _passwordController, + onChanged: (value) => _formKey.currentState?.validate(), + validator: (value) { + if (value != null) { + final regExp = RegExp(r'\d'); + if (regExp.hasMatch(value)) return 'Password is incorrect'; + } + return null; + }, + ), + SizedBox(height: Dimensions.x10), + ...passwordInputExampleRow(ZetaWidgetSize.large), + Divider(height: Dimensions.x20), + ...passwordInputExampleRow(ZetaWidgetSize.medium), + Divider(height: Dimensions.x20), + ...passwordInputExampleRow(ZetaWidgetSize.small), + ], + ), + ), + ), + )); + } +} + +List passwordInputExampleRow( + ZetaWidgetSize size, { + BorderType borderType = BorderType.rounded, +}) { + return [ + ZetaPasswordInput(size: size, hintText: 'Password', borderType: borderType), + SizedBox(height: 20), + ZetaPasswordInput(borderType: borderType, size: size, hintText: 'Password', enabled: false), + SizedBox(height: 20), + ZetaPasswordInput( + size: size, + label: 'Label', + hintText: 'Password', + footerText: 'Default hint text', + borderType: borderType, + footerIcon: ZetaIcons.info_round), + ]; +} diff --git a/example/pubspec.lock b/example/pubspec.lock index 9f1a5058..9c8df3ae 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+12" + version: "0.1.1+15" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/password_input_test.dart b/example/test/password_input_test.dart new file mode 100644 index 00000000..765ede1a --- /dev/null +++ b/example/test/password_input_test.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import 'test_components.dart'; + +void main() { + testWidgets('ZetaPasswordInput initializes correctly', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaPasswordInput(), + ), + ); + expect(find.byType(ZetaPasswordInput), findsOneWidget); + }); + + testWidgets('Test password visibility', (WidgetTester tester) async { + await tester.pumpWidget( + TestWidget( + widget: ZetaPasswordInput(), + ), + ); + final obscureIconOff = find.byIcon(ZetaIcons.visibility_off_sharp); + expect(obscureIconOff, findsOneWidget); + await tester.tap(obscureIconOff); + await tester.pump(); + + final obscureIconOn = find.byIcon(ZetaIcons.visibility_sharp); + expect(obscureIconOn, findsOneWidget); + }); + + testWidgets('Test error message visibility', (WidgetTester tester) async { + String? testValidator(String? value) { + final regExp = RegExp(r'\d'); + if (value != null && regExp.hasMatch(value)) return 'Error'; + return null; + } + + await tester.pumpWidget( + TestWidget( + widget: ZetaPasswordInput( + controller: TextEditingController(), + validator: testValidator, + ), + ), + ); + + final passwordField = find.byType(TextFormField); + await tester.enterText(passwordField, 'password12'); + await tester.pump(); + + expect(find.text('Error'), findsOneWidget); + }); +} diff --git a/example/widgetbook/components/password_input_widgetbook.dart b/example/widgetbook/components/password_input_widgetbook.dart new file mode 100644 index 00000000..937c59ec --- /dev/null +++ b/example/widgetbook/components/password_input_widgetbook.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/password_input_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent passwordInputWidgetBook() { + return WidgetbookComponent( + name: 'Password Input', + useCases: [ + WidgetbookUseCase( + name: 'Rounded', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(Dimensions.x5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: Dimensions.x10), + ...passwordInputExampleRow(ZetaWidgetSize.large), + Divider(height: Dimensions.x20), + ...passwordInputExampleRow(ZetaWidgetSize.medium), + Divider(height: Dimensions.x20), + ...passwordInputExampleRow(ZetaWidgetSize.small), + ], + ), + ), + ), + ), + WidgetbookUseCase( + name: 'Sharp', + builder: (context) => SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(Dimensions.x5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: Dimensions.x10), + ...passwordInputExampleRow(ZetaWidgetSize.large, borderType: BorderType.sharp), + Divider(height: Dimensions.x20), + ...passwordInputExampleRow(ZetaWidgetSize.medium, borderType: BorderType.sharp), + Divider(height: Dimensions.x20), + ...passwordInputExampleRow(ZetaWidgetSize.small, borderType: BorderType.sharp), + ], + ), + ), + ), + ), + ], + ); +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index e27428d3..a3f777bb 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -13,6 +13,7 @@ import 'components/grid_widgetbook.dart'; import 'components/in_page_banner_widgetbook.dart'; import 'components/indicator_widgetbook.dart'; import 'components/menu_items_widgetbook.dart'; +import 'components/password_input_widgetbook.dart'; import 'components/priority_pill_widgetbook.dart'; import 'components/spacing_widgetbook.dart'; import 'components/status_label_widgetbook.dart'; @@ -50,6 +51,7 @@ class HotReload extends StatelessWidget { menuItemsWidgetBook(), accordionWidgetBook(), buttonWidgetBook(), + passwordInputWidgetBook(), bottomSheetWidgetBook(), ], ), diff --git a/lib/src/components/password_input.dart b/lib/src/components/password_input.dart new file mode 100644 index 00000000..d784e35c --- /dev/null +++ b/lib/src/components/password_input.dart @@ -0,0 +1,311 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; + +///Extension for password visibility state handling +extension on ValueNotifier { + void toggle() => value = !value; +} + +///Zeta Password Input +class ZetaPasswordInput extends StatefulWidget { + ///Constructs [ZetaPasswordInput] + const ZetaPasswordInput({ + this.borderType = BorderType.rounded, + this.size = ZetaWidgetSize.large, + this.validator, + this.onChanged, + this.obscureText = true, + this.enabled = true, + this.controller, + this.hintText, + this.label, + this.footerText, + this.footerIcon, + super.key, + }); + + /// Controls the text being edited. + final TextEditingController? controller; + + /// Whether the text is obscured. Useful for passwords. Defaults to true. + final bool obscureText; + + /// Text that suggests what sort of input the field accepts. + final String? hintText; + + /// Whether the input field is enabled or disabled. Defaults to true. + final bool enabled; + + /// Optional label text to display above the input field. + final String? label; + + /// Optional footer text to display below the input field. + final String? footerText; + + /// Optional icon to display beside the footer text. + final IconData? footerIcon; + + /// Defines the border style of the input field. Can be either [BorderType.rounded] or [BorderType.sharp]. + /// Defaults to [BorderType.rounded]. + final BorderType borderType; + + /// Defines the size of the input field. Can be [ZetaWidgetSize.small], [ZetaWidgetSize.medium], or [ZetaWidgetSize.large]. + /// Defaults to [ZetaWidgetSize.large]. + final ZetaWidgetSize size; + + /// An optional method that validates an input. Returns an error string to + /// display if the input is invalid, or null otherwise. + final String? Function(String?)? validator; + + /// Called when the user initiates a change to the [ZetaPasswordInput] + final void Function(String)? onChanged; + + @override + State createState() => _ZetaPasswordInputState(); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add( + DiagnosticsProperty('controller', controller), + ) + ..add(DiagnosticsProperty('obscureText', obscureText)) + ..add(StringProperty('hintText', hintText)) + ..add(DiagnosticsProperty('enabled', enabled)) + ..add(StringProperty('label', label)) + ..add(StringProperty('footerText', footerText)) + ..add(DiagnosticsProperty('footerIcon', footerIcon)) + ..add(EnumProperty('borderType', borderType)) + ..add( + ObjectFlagProperty.has( + 'validator', + validator, + ), + ) + ..add( + ObjectFlagProperty.has( + 'onChanged', + onChanged, + ), + ) + ..add(EnumProperty('size', size)); + } +} + +class _ZetaPasswordInputState extends State { + late final ValueNotifier _obscureTextNotifier; + String? _errorMessage; + + @override + void initState() { + super.initState(); + _obscureTextNotifier = ValueNotifier(widget.obscureText); + widget.controller?.addListener(_validate); + } + + void _validate() { + if (widget.validator != null && widget.controller != null) { + setState( + () => _errorMessage = widget.validator!(widget.controller!.text), + ); + } + } + + @override + void dispose() { + _obscureTextNotifier.dispose(); + widget.controller?.removeListener(_validate); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final theme = Zeta.of(context); + final colors = _ZetaPasswordInputColors(colors: theme.colors); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.label != null) _buildLabel(), + _buildTextField(context), + if (widget.footerText != null || widget.footerIcon != null || _errorMessage != null) _buildFooter(colors), + ], + ); + } + + Widget _buildLabel() { + return Padding( + padding: const EdgeInsets.symmetric(vertical: Dimensions.x1), + child: Text(widget.label!, style: ZetaText.zetaBodyMedium), + ); + } + + Widget _buildTextField(BuildContext context) { + return SizedBox( + height: _getInputHeight(), + child: ValueListenableBuilder( + valueListenable: _obscureTextNotifier, + builder: (context, obscureValue, child) { + return TextFormField( + controller: widget.controller, + obscureText: obscureValue, + onChanged: widget.onChanged, + style: _getTextStyle(), + decoration: _inputDecoration(context), + ); + }, + ), + ); + } + + OutlineInputBorder _getBorder(Color color, {double width = 1}) { + return OutlineInputBorder( + borderSide: BorderSide(color: color, width: width), + borderRadius: BorderRadius.circular( + widget.borderType == BorderType.rounded ? Dimensions.x1 : Dimensions.x0, + ), + ); + } + + InputDecoration _inputDecoration(BuildContext context) { + final theme = Zeta.of(context); + final colors = _ZetaPasswordInputColors(colors: theme.colors); + final defaultBorderColor = _errorMessage != null ? colors.borderErrorColor : colors.borderDefaultColor; + return InputDecoration( + contentPadding: const EdgeInsets.symmetric(horizontal: 8), + filled: true, + fillColor: _getBackgroundColor(colors), + enabledBorder: _getBorder(defaultBorderColor), + focusedBorder: _getBorder( + _errorMessage != null ? colors.borderErrorColor : colors.borderActiveColor, + width: 2, + ), + disabledBorder: _getBorder(colors.borderDisableColor), + border: _getBorder(defaultBorderColor), + enabled: widget.enabled, + hintText: widget.hintText, + hintStyle: _getTextStyle(), + suffixIcon: _buildVisibilityIcon(colors), + ); + } + + Widget _buildFooter(_ZetaPasswordInputColors colors) { + return Padding( + padding: const EdgeInsets.only(top: Dimensions.x1), + child: Row( + children: [ + if (_errorMessage != null) ..._buildError(colors.borderErrorColor), + if (_errorMessage == null && widget.footerIcon != null) ...[ + Icon( + widget.footerIcon, + size: Dimensions.x4, + color: widget.enabled ? colors.hintIconColor : colors.hintIconDisableColor, + ), + const SizedBox(width: Dimensions.x1), + ], + if (_errorMessage == null && widget.footerText != null) ...[ + Text( + widget.footerText!, + style: ZetaText.zetaBodySmall.copyWith( + color: widget.enabled ? colors.hintColor : colors.hintDisableColor, + ), + ), + ], + ], + ), + ); + } + + List _buildError(Color color) { + return [ + Icon( + ZetaIcons.error_round, + size: Dimensions.x4, + color: color, + ), + const SizedBox(width: Dimensions.x1), + Text( + _errorMessage!, + style: ZetaText.zetaBodySmall.copyWith(color: color), + ), + ]; + } + + Widget _buildVisibilityIcon(_ZetaPasswordInputColors colors) { + return ValueListenableBuilder( + valueListenable: _obscureTextNotifier, + builder: (context, value, child) { + return IconButton( + padding: const EdgeInsets.symmetric(vertical: Dimensions.x1), + icon: Icon( + value ? ZetaIcons.visibility_off_sharp : ZetaIcons.visibility_sharp, + size: _getSuffixIconSize(), + ), + color: widget.enabled ? colors.suffixIconColor : colors.suffixIconDisableColor, + onPressed: () => _obscureTextNotifier.toggle(), + ); + }, + ); + } + + Color _getBackgroundColor(_ZetaPasswordInputColors colors) { + if (!widget.enabled) return colors.disableColor; + if (_errorMessage != null) return colors.errorColor; + return colors.defaultColor; + } + + double _getInputHeight() { + switch (widget.size) { + case ZetaWidgetSize.small: + return Dimensions.x8; + case ZetaWidgetSize.medium: + return Dimensions.x10; + case ZetaWidgetSize.large: + return Dimensions.x12; + } + } + + TextStyle _getTextStyle() { + if (widget.size == ZetaWidgetSize.small) return ZetaText.zetaBodySmall; + return ZetaText.zetaBodyMedium; + } + + double _getSuffixIconSize() { + if (widget.size == ZetaWidgetSize.small) return Dimensions.x4; + return Dimensions.x5; + } +} + +class _ZetaPasswordInputColors { + const _ZetaPasswordInputColors({required this.colors}); + + final ZetaColors colors; + + Color get defaultColor => colors.surfacePrimary; + + Color get errorColor => colors.red.shade10; + + Color get disableColor => colors.surfaceDisabled; + + Color get borderDefaultColor => colors.borderSubtle; + + Color get borderErrorColor => colors.negative; + + Color get borderActiveColor => colors.primary; + + Color get borderDisableColor => colors.borderSubtle; + + Color get suffixIconColor => colors.iconDefault; + + Color get suffixIconDisableColor => colors.iconDisabled; + + Color get hintColor => colors.textSubtle; + + Color get hintIconColor => colors.iconSubtle; + + Color get hintDisableColor => colors.textDisabled; + + Color get hintIconDisableColor => colors.iconDisabled; +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 5c20ebdc..004ef2dc 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -12,6 +12,7 @@ export 'src/components/grid.dart'; export 'src/components/in_page_banner.dart'; export 'src/components/indicator.dart'; export 'src/components/menu_items.dart'; +export 'src/components/password_input.dart'; export 'src/components/priority_pill.dart'; export 'src/components/spacing.dart'; export 'src/components/status_label.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index e540da0d..ff3d1f43 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+15 +version: 0.1.1+16 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. From 753a460015cbc074d88fe4eac8ef447ed88d8b6c Mon Sep 17 00:00:00 2001 From: atanasyordanov21 <63714308+atanasyordanov21@users.noreply.github.com> Date: Wed, 10 Jan 2024 14:45:05 +0200 Subject: [PATCH 26/41] Component chip (#46) Co-authored-by: Atanas Yordanov Co-authored-by: github-actions --- example/lib/home.dart | 4 +- example/lib/pages/chip_example.dart | 260 ++++++++++++++++++ ...enu_items.dart => menu_items_example.dart} | 0 example/pubspec.lock | 2 +- .../components/chip_widgetbook.dart | 47 ++++ .../components/menu_items_widgetbook.dart | 2 +- example/widgetbook/widgetbook.dart | 2 + lib/src/components/chip.dart | 252 +++++++++++++++++ lib/zeta_flutter.dart | 1 + 9 files changed, 567 insertions(+), 3 deletions(-) create mode 100644 example/lib/pages/chip_example.dart rename example/lib/pages/{menu_items.dart => menu_items_example.dart} (100%) create mode 100644 example/widgetbook/components/chip_widgetbook.dart create mode 100644 lib/src/components/chip.dart diff --git a/example/lib/home.dart b/example/lib/home.dart index 6b728175..fe96c7d7 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -15,8 +15,9 @@ import 'package:zeta_example/pages/checkbox_example.dart'; import 'package:zeta_example/pages/fab_example/fab_example.dart'; import 'package:zeta_example/pages/fab_example/primary_fab.dart'; import 'package:zeta_example/pages/grid_example.dart'; +import 'package:zeta_example/pages/chip_example.dart'; +import 'package:zeta_example/pages/menu_items_example.dart'; import 'package:zeta_example/pages/in_page_banner_example.dart'; -import 'package:zeta_example/pages/menu_items.dart'; import 'package:zeta_example/pages/password_input_example.dart'; import 'package:zeta_example/pages/priority_pill_example.dart'; import 'package:zeta_example/pages/icons_example.dart'; @@ -69,6 +70,7 @@ final List components = [ Component(FabInverseLargeSharp.name, (context) => const FabInverseLargeSharp()), ]), Component(MenuItemsExample.name, (context) => const MenuItemsExample()), + Component(ChipExample.name, (context) => const ChipExample()), Component(PasswordInputExample.name, (context) => const PasswordInputExample()), Component(BottomSheetExample.name, (context) => const BottomSheetExample()), ]; diff --git a/example/lib/pages/chip_example.dart b/example/lib/pages/chip_example.dart new file mode 100644 index 00000000..a2ad8c21 --- /dev/null +++ b/example/lib/pages/chip_example.dart @@ -0,0 +1,260 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../widgets.dart'; + +class ChipExample extends StatelessWidget { + static const String name = 'Chip'; + + const ChipExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: ChipExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + ...inputChipExample, + const SizedBox(height: 30), + ...assistChipExample, + const SizedBox(height: 30), + ...filterChipExample, + const SizedBox(height: 30), + ...statusChipExample, + ], + ), + ), + ); + }, + ); + } + + static List inputChipExample = [ + Text( + 'Input Chip', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + Text( + 'Rounded', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text('Label Only', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.input(label: 'Label'), + const SizedBox(height: 30), + Text('Label + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.input( + label: 'Label', + onDelete: () {}, + ), + const SizedBox(height: 30), + Text('Label + Avatar', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.input( + label: 'Label', + leading: const Icon(ZetaIcons.avatar), + ), + const SizedBox(height: 30), + Text('Label, Avatar + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.input( + label: 'Label', + leading: const Icon(ZetaIcons.avatar), + onDelete: () {}, + ), + ], + ), + Column( + children: [ + Text( + 'Sharp', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text('Label Only', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.input( + label: 'Label', + rounded: false, + ), + const SizedBox(height: 30), + Text('Label + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.input( + label: 'Label', + rounded: false, + onDelete: () {}, + ), + const SizedBox(height: 30), + Text('Label + Avatar', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.input( + label: 'Label', + rounded: false, + leading: const Icon(ZetaIcons.avatar), + ), + const SizedBox(height: 30), + Text('Label, Avatar + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.input( + label: 'Label', + rounded: false, + leading: const Icon(ZetaIcons.avatar), + onDelete: () {}, + ), + ], + ), + ], + ), + ]; + + static List assistChipExample = [ + Text( + 'Assist Chip', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + Text( + 'Rounded', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text('Label Only', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.assist(label: 'Label'), + const SizedBox(height: 30), + Text('Label + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.assist( + label: 'Label', + showIcon: true, + ), + ], + ), + Column( + children: [ + Text( + 'Sharp', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text('Label Only', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.assist( + label: 'Label', + rounded: false, + ), + const SizedBox(height: 30), + Text('Label + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaChip.assist( + label: 'Label', + rounded: false, + showIcon: true, + ), + ], + ), + ], + ), + ]; + + static List filterChipExample = [ + Text( + 'Filter Chip', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Row( + children: [ + Expanded( + child: Column( + children: [ + Text( + 'Rounded', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + ZetaFilterChip(label: 'Label'), + const SizedBox(height: 10), + ZetaFilterChip( + label: 'Label', + selected: true, + ), + ], + ), + ), + Expanded( + child: Column( + children: [ + Text( + 'Sharp', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + ZetaFilterChip( + label: 'Label', + rounded: false, + ), + const SizedBox(height: 10), + ZetaFilterChip( + label: 'Label', + rounded: false, + selected: true, + ), + ], + ), + ), + ], + ), + ]; + + static List statusChipExample = [ + Text( + 'Status Chip', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + ZetaChip.status('Input Custom'), + const SizedBox(height: 10), + ZetaChip.status('New'), + const SizedBox(height: 10), + ZetaChip.status('In Progress'), + const SizedBox(height: 10), + ZetaChip.status('Completed'), + const SizedBox(height: 10), + ZetaChip.status('Done'), + const SizedBox(height: 10), + ZetaChip.status('Drafting'), + const SizedBox(height: 10), + ZetaChip.status('--'), + ]; +} diff --git a/example/lib/pages/menu_items.dart b/example/lib/pages/menu_items_example.dart similarity index 100% rename from example/lib/pages/menu_items.dart rename to example/lib/pages/menu_items_example.dart diff --git a/example/pubspec.lock b/example/pubspec.lock index 9c8df3ae..3ebb7d1d 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+15" + version: "0.1.1+16" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/widgetbook/components/chip_widgetbook.dart b/example/widgetbook/components/chip_widgetbook.dart new file mode 100644 index 00000000..28e79469 --- /dev/null +++ b/example/widgetbook/components/chip_widgetbook.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/chip_example.dart'; + +WidgetbookComponent chipWidgetBook() { + return WidgetbookComponent( + name: 'Chip', + useCases: [ + WidgetbookUseCase( + name: 'Input Chip', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: ChipExample.inputChipExample, + ), + ), + ), + WidgetbookUseCase( + name: 'Assist Chip', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: ChipExample.assistChipExample, + ), + ), + ), + WidgetbookUseCase( + name: 'Filter Chip', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: ChipExample.filterChipExample, + ), + ), + ), + WidgetbookUseCase( + name: 'Status Chip', + builder: (context) => Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: ChipExample.statusChipExample, + ), + ), + ), + ], + ); +} diff --git a/example/widgetbook/components/menu_items_widgetbook.dart b/example/widgetbook/components/menu_items_widgetbook.dart index 0315b18d..6f391b32 100644 --- a/example/widgetbook/components/menu_items_widgetbook.dart +++ b/example/widgetbook/components/menu_items_widgetbook.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/menu_items.dart'; +import 'package:zeta_example/pages/menu_items_example.dart'; WidgetbookComponent menuItemsWidgetBook() { return WidgetbookComponent( diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index a3f777bb..2edb9b64 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -12,6 +12,7 @@ import 'components/color_widgetbook.dart'; import 'components/grid_widgetbook.dart'; import 'components/in_page_banner_widgetbook.dart'; import 'components/indicator_widgetbook.dart'; +import 'components/chip_widgetbook.dart'; import 'components/menu_items_widgetbook.dart'; import 'components/password_input_widgetbook.dart'; import 'components/priority_pill_widgetbook.dart'; @@ -50,6 +51,7 @@ class HotReload extends StatelessWidget { inPageBannerWidgetBook(), menuItemsWidgetBook(), accordionWidgetBook(), + chipWidgetBook(), buttonWidgetBook(), passwordInputWidgetBook(), bottomSheetWidgetBook(), diff --git a/lib/src/components/chip.dart b/lib/src/components/chip.dart new file mode 100644 index 00000000..590e9781 --- /dev/null +++ b/lib/src/components/chip.dart @@ -0,0 +1,252 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../zeta_flutter.dart'; + +/// The type of [ZetaChip] +enum ZetaChipType { + /// Input Chip + input, + + /// Filter Chip + filter, + + /// Assist Chip + assist, + + /// Status Chip + status, +} + +/// Component [ZetaChip] +class ZetaChip extends StatelessWidget { + /// Constructor for the component [ZetaChip] + const ZetaChip({ + super.key, + required this.type, + required this.label, + this.leading, + this.onDelete, + this.selected = false, + this.rounded = true, + }); + + /// Factory constructor for [ZetaChip] of type `input` + factory ZetaChip.input({ + required String label, + Widget? leading, + VoidCallback? onDelete, + bool rounded = true, + }) { + return ZetaChip( + type: ZetaChipType.input, + label: label, + leading: leading, + onDelete: onDelete, + rounded: rounded, + ); + } + + /// Factory constructor for [ZetaChip] of type `input` + factory ZetaChip.assist({ + required String label, + bool showIcon = false, + Widget? icon, + bool rounded = true, + }) { + final Widget? chipIcon = showIcon ? (icon ?? Icon(rounded ? ZetaIcons.star_round : ZetaIcons.star_sharp)) : null; + return ZetaChip( + type: ZetaChipType.assist, + label: label, + leading: chipIcon, + rounded: rounded, + ); + } + + /// Factory constructor for [ZetaChip] of type `status` + factory ZetaChip.status(String label) { + return ZetaChip( + type: ZetaChipType.status, + label: label, + ); + } + + /// The type of [ZetaChip] + final ZetaChipType type; + + /// The label on the [ZetaChip] + final String label; + + /// The leading icon + final Widget? leading; + + /// The delete action + final VoidCallback? onDelete; + + /// Initial status for the `filter` chiup + final bool selected; + + /// Sets rounded or sharp border. + /// Default is `true`. + final bool rounded; + + @override + Widget build(BuildContext context) { + final colors = Zeta.of(context).colors; + final avatarSize = type == ZetaChipType.input ? 24.0 : 20.0; + final bgColor = type == ZetaChipType.status + ? colors.warm.shade30 + : selected + ? colors.textDefault + : colors.surfacePrimary; + + return Chip( + backgroundColor: bgColor, + label: Text(label, textAlign: TextAlign.center), + labelStyle: type == ZetaChipType.status + ? ZetaText.zetaBodyXSmall + : ZetaText.zetaBodySmall.apply(color: selected ? colors.textInverse : colors.textDefault), + labelPadding: type == ZetaChipType.status + ? const EdgeInsets.symmetric(horizontal: 10) + : EdgeInsets.fromLTRB( + leading == null ? 14 : 2.5, + 2, + onDelete == null ? 14 : 2.5, + 2, + ), + padding: EdgeInsets.zero, + visualDensity: VisualDensity.compact, + side: BorderSide(color: type == ZetaChipType.status ? bgColor : colors.borderDefault), + shape: RoundedRectangleBorder( + borderRadius: rounded ? BorderRadius.circular(type == ZetaChipType.status ? 6 : 100) : BorderRadius.zero, + ), + clipBehavior: Clip.hardEdge, + avatar: leading == null + ? null + : Container( + width: avatarSize, + height: avatarSize, + decoration: BoxDecoration( + color: bgColor, + borderRadius: BorderRadius.circular(24), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(24), + clipBehavior: Clip.hardEdge, + child: IconTheme( + data: IconThemeData( + color: _getAvatarColor(type, colors), + size: avatarSize, + ), + child: leading!, + ), + ), + ), + deleteIcon: onDelete == null + ? null + : Icon( + Icons.close, + size: 18, + color: colors.iconDefault, + ), + onDeleted: onDelete, + ); + } + + static Color _getAvatarColor(ZetaChipType type, ZetaColors colors) { + switch (type) { + case ZetaChipType.input: + return colors.cool; + case ZetaChipType.filter: + return colors.iconInverse; + case ZetaChipType.assist: + return colors.iconDefault; + case ZetaChipType.status: + return colors.iconDefault; + } + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', type)) + ..add(DiagnosticsProperty('label', label)) + ..add(DiagnosticsProperty('onDelete', onDelete)) + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(DiagnosticsProperty('selected', selected)); + } +} + +/// Component [ZetaFilterChip] +class ZetaFilterChip extends StatefulWidget { + /// Constructor for [ZetaFilterChip] + const ZetaFilterChip({ + super.key, + required this.label, + this.selected = false, + this.onChange, + this.rounded = true, + }); + + /// The label on the [ZetaFilterChip] + final String label; + + /// Initial status + final bool selected; + + /// On change + final void Function({bool value})? onChange; + + /// Sets rounded or sharp border. + /// Default is `true`. + final bool rounded; + + @override + State createState() => _ZetaFilterChipState(); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('label', label)) + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(DiagnosticsProperty('selected', selected)) + ..add(DiagnosticsProperty('onChange', onChange)); + } +} + +class _ZetaFilterChipState extends State { + late bool _selected; + + @override + void initState() { + super.initState(); + _selected = widget.selected; + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + setState(() { + _selected = !_selected; + }); + widget.onChange?.call(value: _selected); + }, + child: _selected + ? ZetaChip( + type: ZetaChipType.filter, + label: widget.label, + leading: const Icon(Icons.check), + selected: _selected, + rounded: widget.rounded, + ) + : ZetaChip( + type: ZetaChipType.filter, + label: widget.label, + rounded: widget.rounded, + ), + ); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 004ef2dc..9f034835 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -7,6 +7,7 @@ export 'src/components/badge.dart'; export 'src/components/bottom_sheet.dart'; export 'src/components/button.dart'; export 'src/components/checkbox.dart'; +export 'src/components/chip.dart'; export 'src/components/fab.dart'; export 'src/components/grid.dart'; export 'src/components/in_page_banner.dart'; From aff41a372a2e3ba7eef06e1d69dc3e57b423c3dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jan 2024 12:45:33 +0000 Subject: [PATCH 27/41] chore(deps): bump tj-actions/changed-files from 35 to 41 in /.github/workflows (#48) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 35 to 41.
    Release notes

    Sourced from tj-actions/changed-files's releases.

    v41

    Changes in v41.0.1

    What's Changed

    Full Changelog: https://github.com/tj-actions/changed-files/compare/v41...v41.0.1


    Changes in v41.0.0

    🔥 🔥 BREAKING CHANGE 🔥 🔥

    A new safe_output input is now available to prevent outputting unsafe filename characters (Enabled by default). This would escape characters in the filename that could be used for command injection.

    [!NOTE] This can be disabled by setting the safe_output to false this comes with a recommendation to store all outputs generated in an environment variable first before using them.

    Example

    ...
        - name: Get changed files
          id: changed-files
          uses: tj-actions/changed-files@v40
          with:
    safe_output: false # set to false because we are using an environment
    variable to store the output and avoid command injection.
    
    - name: List all added files
      env:
        ADDED_FILES: ${{ steps.changed-files.outputs.added_files }}
      run: |
        for file in &quot;$ADDED_FILES&quot;; do
          echo &quot;$file was added&quot;
        done
    

    ...

    What's Changed

    ... (truncated)

    Changelog

    Sourced from tj-actions/changed-files's changelog.

    Changelog

    41.0.1 - (2023-12-24)

    🐛 Bug Fixes

    • Update characters escaped by safe output (#1815) (716b1e1) - (Tonye Jack)

    ⚙️ Miscellaneous Tasks

    • deps: Update dependency eslint-plugin-prettier to v5.1.2 (7aaf10d) - (renovate[bot])

    ⬆️ Upgrades

    • Upgraded to v41 (#1811)

    Co-authored-by: jackton1 jackton1@users.noreply.github.com (cc08e17) - (tj-actions[bot])

    41.0.0 - (2023-12-23)

    🐛 Bug Fixes

    • Update safe output regex and the docs (#1805) (ff2f6e6) - (tj-actions[bot])

    ⏪ Reverts

    • Revert "chore(deps): update actions/download-artifact action to v4" (#1806)

    (4f573fe) - (Tonye Jack)

    🔄 Update

    • Update README.md (6e79d6e) - (Tonye Jack)
    • Update README.md (d13ac19) - (Tonye Jack)
    • Update README.md (bb89f97) - (Tonye Jack)
    • Updated README.md (#1810)

    Co-authored-by: renovate[bot] (1864078) - (tj-actions[bot])

    • Update README.md (#1808)

    (47371c5) - (Tonye Jack)

    📝 Other

    • Merge pull request from GHSA-mcph-m25j-8j63
    • feat: add safe_output input enabled by default

    • fix: migrate README to safe uses of interpolation

    ... (truncated)

    Commits

    [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tj-actions/changed-files&package-manager=github_actions&previous-version=35&new-version=41)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
    Dependabot commands and options
    You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/zebratechnologies/zeta-flutter/network/alerts).
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/onMerge.yml | 2 +- .github/workflows/pr.yml | 2 +- CHANGELOG.md | 291 +++++++++++++++++++++++++++++++++- pubspec.yaml | 2 +- 4 files changed, 292 insertions(+), 5 deletions(-) diff --git a/.github/workflows/onMerge.yml b/.github/workflows/onMerge.yml index 18736e3c..f501eb7c 100644 --- a/.github/workflows/onMerge.yml +++ b/.github/workflows/onMerge.yml @@ -19,7 +19,7 @@ jobs: persist-credentials: false - name: Get all changed *.dart, files in docs or pubspec.yaml id: changed-files - uses: tj-actions/changed-files@v35 + uses: tj-actions/changed-files@v41 with: files: | **/*.dart diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index ad790cbb..244a6311 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -16,7 +16,7 @@ jobs: persist-credentials: false - name: Get all changed *.dart, files in custom-docs or pubspec.yaml id: changed-files - uses: tj-actions/changed-files@v35 + uses: tj-actions/changed-files@v41 with: base_sha: ${{ github.event.pull_request.base.sha }} sha: ${{ github.event.pull_request.head.sha }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6803a8c8..1d5a0d4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,289 @@ +## [0.1.1+18] - 2024-01-10 +### :flying_saucer: Other Changes +- [`caea7bd`](https://github.com/zebratechnologies/zeta-flutter/commit/caea7bdc061149db64344526bd16cd5232a219c2) - chore(deps): bump tj-actions/changed-files from 35 to 41 in /.github/workflows ([#48](https://github.com/zebratechnologies/zeta-flutter/pull/48)) + +Bumps +[tj-actions/changed-files](https://github.com/tj-actions/changed-files) +from 35 to 41. +
    +Release notes +

    Sourced from tj-actions/changed-files's +releases.

    +
    +

    v41

    +

    Changes in v41.0.1

    +

    What's Changed

    + +

    Full Changelog: https://github.com/tj-actions/changed-files/compare/v41...v41.0.1

    +
    +

    Changes in v41.0.0

    +

    🔥 🔥 BREAKING CHANGE 🔥 🔥

    +

    A new safe_output input is now available to prevent +outputting unsafe filename characters (Enabled by default). This would +escape characters in the filename that could be used for command +injection.

    +
    +

    [!NOTE] +This can be disabled by setting the safe_output to false +this comes with a recommendation to store all outputs generated in an +environment variable first before using them.

    +
    +

    Example

    +
    ...
    +    - name: Get changed files
    +      id: changed-files
    +      uses: tj-actions/changed-files@v40
    +      with:
    +safe_output: false # set to false because we are using an environment
    +variable to store the output and avoid command injection.
    +
    - name: List all added files
    +  env:
    +    ADDED_FILES: ${{ steps.changed-files.outputs.added_files }}
    +  run: |
    +    for file in &quot;$ADDED_FILES&quot;; do
    +      echo &quot;$file was added&quot;
    +    done
    +
    +

    ... +

    +

    What's Changed

    + + +
    +

    ... (truncated)

    +
    +
    +Changelog +

    Sourced from tj-actions/changed-files's +changelog.

    +
    +

    Changelog

    +

    41.0.1 +- (2023-12-24)

    +

    🐛 Bug Fixes

    + +

    ⚙️ Miscellaneous Tasks

    +
      +
    • deps: Update dependency eslint-plugin-prettier to +v5.1.2 (7aaf10d) +- (renovate[bot])
    • +
    +

    ⬆️ Upgrades

    + +

    Co-authored-by: jackton1 jackton1@users.noreply.github.com +(cc08e17) +- (tj-actions[bot])

    +

    41.0.0 +- (2023-12-23)

    +

    🐛 Bug Fixes

    + +

    ⏪ Reverts

    + +

    (4f573fe) +- (Tonye Jack)

    +

    🔄 Update

    + +

    Co-authored-by: renovate[bot] (1864078) +- (tj-actions[bot])

    + +

    (47371c5) +- (Tonye Jack)

    +

    📝 Other

    +
      +
    • Merge pull request from GHSA-mcph-m25j-8j63
    • +
    +
      +
    • +

      feat: add safe_output input enabled by default

      +
    • +
    • +

      fix: migrate README to safe uses of interpolation

      +
    • +
    + +
    +

    ... (truncated)

    +
    +
    +Commits + +
    +
    + + +[![Dependabot compatibility +score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tj-actions/changed-files&package-manager=github_actions&previous-version=35&new-version=41)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) + +Dependabot will resolve any conflicts with this PR as long as you don't +alter it yourself. You can also trigger a rebase manually by commenting +`@dependabot rebase`. + +[//]: # (dependabot-automerge-start) +[//]: # (dependabot-automerge-end) + +--- + +
    +Dependabot commands and options +
    + +You can trigger Dependabot actions by commenting on this PR: +- `@dependabot rebase` will rebase this PR +- `@dependabot recreate` will recreate this PR, overwriting any edits +that have been made to it +- `@dependabot merge` will merge this PR after your CI passes on it +- `@dependabot squash and merge` will squash and merge this PR after +your CI passes on it +- `@dependabot cancel merge` will cancel a previously requested merge +and block automerging +- `@dependabot reopen` will reopen this PR if it is closed +- `@dependabot close` will close this PR and stop Dependabot recreating +it. You can achieve the same result by closing it manually +- `@dependabot show ignore conditions` will show all +of the ignore conditions of the specified dependency +- `@dependabot ignore this major version` will close this PR and stop +Dependabot creating any more for this major version (unless you reopen +the PR or upgrade to it yourself) +- `@dependabot ignore this minor version` will close this PR and stop +Dependabot creating any more for this minor version (unless you reopen +the PR or upgrade to it yourself) +- `@dependabot ignore this dependency` will close this PR and stop +Dependabot creating any more for this dependency (unless you reopen the +PR or upgrade to it yourself) +You can disable automated security fix PRs for this repo from the +[Security Alerts +page](https://github.com/zebratechnologies/zeta-flutter/network/alerts). + +
    + +Signed-off-by: dependabot[bot] +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@dependabot[bot]](https://github.com/apps/dependabot))* + + ## [0.1.1+16] - 2024-01-02 ### :flying_saucer: Other Changes - [`225a059`](https://github.com/zebratechnologies/zeta-flutter/commit/225a059aa191f595db4982960c854c2e94c5bdc4) - create bottom sheet ([#45](https://github.com/zebratechnologies/zeta-flutter/pull/45)) @@ -6,7 +292,7 @@ Co-authored-by: Atanas Yordanov Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - [`656ca24`](https://github.com/zebratechnologies/zeta-flutter/commit/656ca2470112a171064f0d2d7477bf087a4f98bd) - Password input ([#47](https://github.com/zebratechnologies/zeta-flutter/pull/47)) -Co-authored-by: github-actions +Co-authored-by: github-actions Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* @@ -1139,4 +1425,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+13]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+12...0.1.1+13 [0.1.1+14]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+13...0.1.1+14 [0.1.1+15]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+14...0.1.1+15 -[0.1.1+16]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+15...0.1.1+16 \ No newline at end of file +[0.1.1+16]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+15...0.1.1+16 +[0.1.1+18]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+17...0.1.1+18 \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index ff3d1f43..08429bf0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+16 +version: 0.1.1+18 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. From 67872203f0dc96de02e6945f0ac4409f95872262 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Wed, 17 Jan 2024 12:06:15 +0000 Subject: [PATCH 28/41] chore: Organize ilb/ to match web (#49) https://jira.zebra.com/browse/UX-911 --------- Co-authored-by: github-actions --- .github/workflows/onMerge.yml | 31 +- CHANGELOG.md | 849 ++++++++++++------ example/pubspec.lock | 2 +- lib/src/{ => assets}/icons.dart | 0 .../components/{ => accordion}/accordion.dart | 2 +- lib/src/components/{ => avatars}/avatar.dart | 2 +- lib/src/components/{ => badges}/badge.dart | 2 +- .../components/{ => badges}/indicator.dart | 2 +- .../{ => badges}/priority_pill.dart | 2 +- .../components/{ => badges}/status_label.dart | 2 +- lib/src/components/{ => badges}/tag.dart | 2 +- .../{ => badges}/workcloud_indicator.dart | 2 +- .../{ => banners}/in_page_banner.dart | 4 +- .../{ => banners}/system_banner.dart | 2 +- .../{ => bottom sheets}/bottom_sheet.dart | 2 +- .../{ => bottom sheets}/menu_items.dart | 2 +- lib/src/components/{ => buttons}/button.dart | 2 +- lib/src/components/{ => buttons}/fab.dart | 2 +- .../components/{ => checkbox}/checkbox.dart | 2 +- lib/src/components/{ => chip}/chip.dart | 2 +- .../{ => password}/password_input.dart | 2 +- lib/src/{components => legacy}/grid.dart | 2 +- lib/src/{components => legacy}/spacing.dart | 2 +- lib/src/{components => legacy}/text.dart | 2 +- lib/src/{ => theme}/tokens.dart | 2 +- lib/zeta_flutter.dart | 44 +- pubspec.yaml | 2 +- 27 files changed, 619 insertions(+), 353 deletions(-) rename lib/src/{ => assets}/icons.dart (100%) rename lib/src/components/{ => accordion}/accordion.dart (99%) rename lib/src/components/{ => avatars}/avatar.dart (99%) rename lib/src/components/{ => badges}/badge.dart (98%) rename lib/src/components/{ => badges}/indicator.dart (99%) rename lib/src/components/{ => badges}/priority_pill.dart (98%) rename lib/src/components/{ => badges}/status_label.dart (99%) rename lib/src/components/{ => badges}/tag.dart (99%) rename lib/src/components/{ => badges}/workcloud_indicator.dart (99%) rename lib/src/components/{ => banners}/in_page_banner.dart (98%) rename lib/src/components/{ => banners}/system_banner.dart (99%) rename lib/src/components/{ => bottom sheets}/bottom_sheet.dart (98%) rename lib/src/components/{ => bottom sheets}/menu_items.dart (99%) rename lib/src/components/{ => buttons}/button.dart (99%) rename lib/src/components/{ => buttons}/fab.dart (99%) rename lib/src/components/{ => checkbox}/checkbox.dart (99%) rename lib/src/components/{ => chip}/chip.dart (99%) rename lib/src/components/{ => password}/password_input.dart (99%) rename lib/src/{components => legacy}/grid.dart (99%) rename lib/src/{components => legacy}/spacing.dart (99%) rename lib/src/{components => legacy}/text.dart (99%) rename lib/src/{ => theme}/tokens.dart (98%) diff --git a/.github/workflows/onMerge.yml b/.github/workflows/onMerge.yml index f501eb7c..eff5b98a 100644 --- a/.github/workflows/onMerge.yml +++ b/.github/workflows/onMerge.yml @@ -48,7 +48,7 @@ jobs: - name: push change id: update run: | - git remote set-url origin https://${{ secrets.PAT}}@github.com/zebratechnologies/zeta-flutter.git + git remote set-url origin https://${{ secrets.PERSONAL_ACCESS_TOKEN}}@github.com/zebratechnologies/zeta-flutter.git git config --global user.name "github-actions" git config --global user.email "github-actions@github.com" git add -A @@ -81,7 +81,7 @@ jobs: id: changelog uses: requarks/changelog-action@v1 with: - token: ${{ secrets.PAT }} + token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} tag: ${{ steps.read-version.outputs.version-number }} excludeTypes: "" includeInvalidCommits: true @@ -91,7 +91,7 @@ jobs: - name: Update changes in zeta-flutter repository if: env.modified == 'true' run: | - git remote set-url origin https://${{ secrets.PAT}}@github.com/zebratechnologies/zeta-flutter.git + git remote set-url origin https://${{ secrets.PERSONAL_ACCESS_TOKEN}}@github.com/zebratechnologies/zeta-flutter.git git config --global user.name "github-actions" git config --global user.email "github-actions@github.com" git add -A @@ -102,7 +102,7 @@ jobs: - name: Push changelog to Zeta uses: dmnemec/copy_file_to_another_repo_action@main env: - API_TOKEN_GITHUB: ${{ secrets.PAT }} + API_TOKEN_GITHUB: ${{ secrets.PERSONAL_ACCESS_TOKEN }} with: source_file: "CHANGELOG_FLUTTER.md" destination_repo: "zebratechnologies/zeta" @@ -111,26 +111,3 @@ jobs: user_email: "github-actions@github.com" user_name: "github-actions" commit_message: "flutter changelog" - - name: Push docs to Zeta - uses: dmnemec/copy_file_to_another_repo_action@main - env: - API_TOKEN_GITHUB: ${{ secrets.PAT }} - with: - source_file: "custom-docs/" - destination_repo: "zebratechnologies/zeta" - destination_folder: "./" - destination_branch: "flutter/${{ steps.read-version.outputs.version-number }}" - user_email: "github-actions@github.com" - user_name: "github-actions" - commit_message: "flutter doc" - - name: Open Zeta PR - uses: thecanadianroot/open-pull-request-action@v1.0.3 - with: - token: ${{secrets.PAT}} - base: main - head: "flutter/${{ steps.read-version.outputs.version-number }}" - title: "flutter/${{ steps.read-version.outputs.version-number }}" - labels: flutter - reviewers: benken - owner: zebratechnologies - repository: zebratechnologies/zeta diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d5a0d4b..53179ba5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,286 +1,574 @@ +## [0.1.1+19] - 2024-01-17 +### :wrench: Chores +- [`d1c0125`](https://github.com/zebratechnologies/zeta-flutter/commit/d1c012523e16ebbf3f38c7028598660cfc7b7ea9) - Organize ilb/ to match web *(PR [#49](https://github.com/zebratechnologies/zeta-flutter/pull/49) by [@thelukewalton](https://github.com/thelukewalton))* + +### :flying_saucer: Other Changes +- [`aff41a3`](https://github.com/zebratechnologies/zeta-flutter/commit/aff41a372a2e3ba7eef06e1d69dc3e57b423c3dd) - chore(deps): bump tj-actions/changed-files from 35 to 41 in /.github/workflows ([#48](https://github.com/zebratechnologies/zeta-flutter/pull/48)) + +Bumps +[tj-actions/changed-files](https://github.com/tj-actions/changed-files) +from 35 to 41. +
    +Release notes +

    Sourced from tj-actions/changed-files's +releases.

    +
    +

    v41

    +

    Changes in v41.0.1

    +

    What's Changed

    + +

    Full Changelog: https://github.com/tj-actions/changed-files/compare/v41...v41.0.1

    +
    +

    Changes in v41.0.0

    +

    🔥 🔥 BREAKING CHANGE 🔥 🔥

    +

    A new safe_output input is now available to prevent +outputting unsafe filename characters (Enabled by default). This would +escape characters in the filename that could be used for command +injection.

    +
    +

    [!NOTE] +This can be disabled by setting the safe_output to false +this comes with a recommendation to store all outputs generated in an +environment variable first before using them.

    +
    +

    Example

    +
    ...
    +    - name: Get changed files
    +      id: changed-files
    +      uses: tj-actions/changed-files@v40
    +      with:
    +safe_output: false # set to false because we are using an environment
    +variable to store the output and avoid command injection.
    +
    - name: List all added files
    +  env:
    +    ADDED_FILES: ${{ steps.changed-files.outputs.added_files }}
    +  run: |
    +    for file in &quot;$ADDED_FILES&quot;; do
    +      echo &quot;$file was added&quot;
    +    done
    +
    +

    ... +

    +

    What's Changed

    + + +
    +

    ... (truncated)

    +
    +
    +Changelog +

    Sourced from tj-actions/changed-files's +changelog.

    +
    +

    Changelog

    +

    41.0.1 +- (2023-12-24)

    +

    🐛 Bug Fixes

    + +

    ⚙️ Miscellaneous Tasks

    +
      +
    • deps: Update dependency eslint-plugin-prettier to +v5.1.2 (7aaf10d) +- (renovate[bot])
    • +
    +

    ⬆️ Upgrades

    + +

    Co-authored-by: jackton1 jackton1@users.noreply.github.com +(cc08e17) +- (tj-actions[bot])

    +

    41.0.0 +- (2023-12-23)

    +

    🐛 Bug Fixes

    + +

    ⏪ Reverts

    + +

    (4f573fe) +- (Tonye Jack)

    +

    🔄 Update

    + +

    Co-authored-by: renovate[bot] (1864078) +- (tj-actions[bot])

    + +

    (47371c5) +- (Tonye Jack)

    +

    📝 Other

    +
      +
    • Merge pull request from GHSA-mcph-m25j-8j63
    • +
    +
      +
    • +

      feat: add safe_output input enabled by default

      +
    • +
    • +

      fix: migrate README to safe uses of interpolation

      +
    • +
    + +
    +

    ... (truncated)

    +
    +
    +Commits + +
    +
    + +[![Dependabot compatibility +score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tj-actions/changed-files&package-manager=github_actions&previous-version=35&new-version=41)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) + +Dependabot will resolve any conflicts with this PR as long as you don't +alter it yourself. You can also trigger a rebase manually by commenting +`@dependabot rebase`. + +[//]: # (dependabot-automerge-start) +[//]: # (dependabot-automerge-end) + +--- + +
    +Dependabot commands and options +
    + +You can trigger Dependabot actions by commenting on this PR: +- `@dependabot rebase` will rebase this PR +- `@dependabot recreate` will recreate this PR, overwriting any edits +that have been made to it +- `@dependabot merge` will merge this PR after your CI passes on it +- `@dependabot squash and merge` will squash and merge this PR after +your CI passes on it +- `@dependabot cancel merge` will cancel a previously requested merge +and block automerging +- `@dependabot reopen` will reopen this PR if it is closed +- `@dependabot close` will close this PR and stop Dependabot recreating +it. You can achieve the same result by closing it manually +- `@dependabot show ignore conditions` will show all +of the ignore conditions of the specified dependency +- `@dependabot ignore this major version` will close this PR and stop +Dependabot creating any more for this major version (unless you reopen +the PR or upgrade to it yourself) +- `@dependabot ignore this minor version` will close this PR and stop +Dependabot creating any more for this minor version (unless you reopen +the PR or upgrade to it yourself) +- `@dependabot ignore this dependency` will close this PR and stop +Dependabot creating any more for this dependency (unless you reopen the +PR or upgrade to it yourself) +You can disable automated security fix PRs for this repo from the +[Security Alerts +page](https://github.com/zebratechnologies/zeta-flutter/network/alerts). + +
    + +Signed-off-by: dependabot[bot] +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@dependabot[bot]](https://github.com/apps/dependabot))* + + ## [0.1.1+18] - 2024-01-10 ### :flying_saucer: Other Changes - [`caea7bd`](https://github.com/zebratechnologies/zeta-flutter/commit/caea7bdc061149db64344526bd16cd5232a219c2) - chore(deps): bump tj-actions/changed-files from 35 to 41 in /.github/workflows ([#48](https://github.com/zebratechnologies/zeta-flutter/pull/48)) -Bumps -[tj-actions/changed-files](https://github.com/tj-actions/changed-files) -from 35 to 41. -
    -Release notes -

    Sourced from tj-actions/changed-files's -releases.

    -
    -

    v41

    -

    Changes in v41.0.1

    -

    What's Changed

    - -

    Full Changelog: https://github.com/tj-actions/changed-files/compare/v41...v41.0.1

    -
    -

    Changes in v41.0.0

    -

    🔥 🔥 BREAKING CHANGE 🔥 🔥

    -

    A new safe_output input is now available to prevent -outputting unsafe filename characters (Enabled by default). This would -escape characters in the filename that could be used for command -injection.

    -
    -

    [!NOTE] -This can be disabled by setting the safe_output to false -this comes with a recommendation to store all outputs generated in an -environment variable first before using them.

    -
    -

    Example

    -
    ...
    -    - name: Get changed files
    -      id: changed-files
    -      uses: tj-actions/changed-files@v40
    -      with:
    -safe_output: false # set to false because we are using an environment
    -variable to store the output and avoid command injection.
    -
    - name: List all added files
    -  env:
    -    ADDED_FILES: ${{ steps.changed-files.outputs.added_files }}
    -  run: |
    -    for file in &quot;$ADDED_FILES&quot;; do
    -      echo &quot;$file was added&quot;
    -    done
    -
    -

    ... -

    -

    What's Changed

    - - -
    -

    ... (truncated)

    -
    -
    -Changelog -

    Sourced from tj-actions/changed-files's -changelog.

    -
    -

    Changelog

    -

    41.0.1 -- (2023-12-24)

    -

    🐛 Bug Fixes

    - -

    ⚙️ Miscellaneous Tasks

    -
      -
    • deps: Update dependency eslint-plugin-prettier to -v5.1.2 (7aaf10d) -- (renovate[bot])
    • -
    -

    ⬆️ Upgrades

    - -

    Co-authored-by: jackton1 jackton1@users.noreply.github.com -(cc08e17) -- (tj-actions[bot])

    -

    41.0.0 -- (2023-12-23)

    -

    🐛 Bug Fixes

    - -

    ⏪ Reverts

    - -

    (4f573fe) -- (Tonye Jack)

    -

    🔄 Update

    - -

    Co-authored-by: renovate[bot] (1864078) -- (tj-actions[bot])

    - -

    (47371c5) -- (Tonye Jack)

    -

    📝 Other

    -
      -
    • Merge pull request from GHSA-mcph-m25j-8j63
    • -
    -
      -
    • -

      feat: add safe_output input enabled by default

      -
    • -
    • -

      fix: migrate README to safe uses of interpolation

      -
    • -
    - -
    -

    ... (truncated)

    -
    -
    -Commits - -
    -
    - - -[![Dependabot compatibility -score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tj-actions/changed-files&package-manager=github_actions&previous-version=35&new-version=41)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) - -Dependabot will resolve any conflicts with this PR as long as you don't -alter it yourself. You can also trigger a rebase manually by commenting -`@dependabot rebase`. - -[//]: # (dependabot-automerge-start) -[//]: # (dependabot-automerge-end) - ---- - -
    -Dependabot commands and options -
    - -You can trigger Dependabot actions by commenting on this PR: -- `@dependabot rebase` will rebase this PR -- `@dependabot recreate` will recreate this PR, overwriting any edits -that have been made to it -- `@dependabot merge` will merge this PR after your CI passes on it -- `@dependabot squash and merge` will squash and merge this PR after -your CI passes on it -- `@dependabot cancel merge` will cancel a previously requested merge -and block automerging -- `@dependabot reopen` will reopen this PR if it is closed -- `@dependabot close` will close this PR and stop Dependabot recreating -it. You can achieve the same result by closing it manually -- `@dependabot show ignore conditions` will show all -of the ignore conditions of the specified dependency -- `@dependabot ignore this major version` will close this PR and stop -Dependabot creating any more for this major version (unless you reopen -the PR or upgrade to it yourself) -- `@dependabot ignore this minor version` will close this PR and stop -Dependabot creating any more for this minor version (unless you reopen -the PR or upgrade to it yourself) -- `@dependabot ignore this dependency` will close this PR and stop -Dependabot creating any more for this dependency (unless you reopen the -PR or upgrade to it yourself) -You can disable automated security fix PRs for this repo from the -[Security Alerts -page](https://github.com/zebratechnologies/zeta-flutter/network/alerts). - -
    - -Signed-off-by: dependabot[bot] +Bumps +[tj-actions/changed-files](https://github.com/tj-actions/changed-files) +from 35 to 41. +
    +Release notes +

    Sourced from tj-actions/changed-files's +releases.

    +
    +

    v41

    +

    Changes in v41.0.1

    +

    What's Changed

    + +

    Full Changelog: https://github.com/tj-actions/changed-files/compare/v41...v41.0.1

    +
    +

    Changes in v41.0.0

    +

    🔥 🔥 BREAKING CHANGE 🔥 🔥

    +

    A new safe_output input is now available to prevent +outputting unsafe filename characters (Enabled by default). This would +escape characters in the filename that could be used for command +injection.

    +
    +

    [!NOTE] +This can be disabled by setting the safe_output to false +this comes with a recommendation to store all outputs generated in an +environment variable first before using them.

    +
    +

    Example

    +
    ...
    +    - name: Get changed files
    +      id: changed-files
    +      uses: tj-actions/changed-files@v40
    +      with:
    +safe_output: false # set to false because we are using an environment
    +variable to store the output and avoid command injection.
    +
    - name: List all added files
    +  env:
    +    ADDED_FILES: ${{ steps.changed-files.outputs.added_files }}
    +  run: |
    +    for file in &quot;$ADDED_FILES&quot;; do
    +      echo &quot;$file was added&quot;
    +    done
    +
    +

    ... +

    +

    What's Changed

    + + +
    +

    ... (truncated)

    +
    +
    +Changelog +

    Sourced from tj-actions/changed-files's +changelog.

    +
    +

    Changelog

    +

    41.0.1 +- (2023-12-24)

    +

    🐛 Bug Fixes

    + +

    ⚙️ Miscellaneous Tasks

    +
      +
    • deps: Update dependency eslint-plugin-prettier to +v5.1.2 (7aaf10d) +- (renovate[bot])
    • +
    +

    ⬆️ Upgrades

    + +

    Co-authored-by: jackton1 jackton1@users.noreply.github.com +(cc08e17) +- (tj-actions[bot])

    +

    41.0.0 +- (2023-12-23)

    +

    🐛 Bug Fixes

    + +

    ⏪ Reverts

    + +

    (4f573fe) +- (Tonye Jack)

    +

    🔄 Update

    + +

    Co-authored-by: renovate[bot] (1864078) +- (tj-actions[bot])

    + +

    (47371c5) +- (Tonye Jack)

    +

    📝 Other

    +
      +
    • Merge pull request from GHSA-mcph-m25j-8j63
    • +
    +
      +
    • +

      feat: add safe_output input enabled by default

      +
    • +
    • +

      fix: migrate README to safe uses of interpolation

      +
    • +
    + +
    +

    ... (truncated)

    +
    +
    +Commits + +
    +
    + + +[![Dependabot compatibility +score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tj-actions/changed-files&package-manager=github_actions&previous-version=35&new-version=41)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) + +Dependabot will resolve any conflicts with this PR as long as you don't +alter it yourself. You can also trigger a rebase manually by commenting +`@dependabot rebase`. + +[//]: # (dependabot-automerge-start) +[//]: # (dependabot-automerge-end) + +--- + +
    +Dependabot commands and options +
    + +You can trigger Dependabot actions by commenting on this PR: +- `@dependabot rebase` will rebase this PR +- `@dependabot recreate` will recreate this PR, overwriting any edits +that have been made to it +- `@dependabot merge` will merge this PR after your CI passes on it +- `@dependabot squash and merge` will squash and merge this PR after +your CI passes on it +- `@dependabot cancel merge` will cancel a previously requested merge +and block automerging +- `@dependabot reopen` will reopen this PR if it is closed +- `@dependabot close` will close this PR and stop Dependabot recreating +it. You can achieve the same result by closing it manually +- `@dependabot show ignore conditions` will show all +of the ignore conditions of the specified dependency +- `@dependabot ignore this major version` will close this PR and stop +Dependabot creating any more for this major version (unless you reopen +the PR or upgrade to it yourself) +- `@dependabot ignore this minor version` will close this PR and stop +Dependabot creating any more for this minor version (unless you reopen +the PR or upgrade to it yourself) +- `@dependabot ignore this dependency` will close this PR and stop +Dependabot creating any more for this dependency (unless you reopen the +PR or upgrade to it yourself) +You can disable automated security fix PRs for this repo from the +[Security Alerts +page](https://github.com/zebratechnologies/zeta-flutter/network/alerts). + +
    + +Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@dependabot[bot]](https://github.com/apps/dependabot))* @@ -1426,4 +1714,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+14]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+13...0.1.1+14 [0.1.1+15]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+14...0.1.1+15 [0.1.1+16]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+15...0.1.1+16 -[0.1.1+18]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+17...0.1.1+18 \ No newline at end of file +[0.1.1+18]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+17...0.1.1+18 +[0.1.1+19]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+18...0.1.1+19 \ No newline at end of file diff --git a/example/pubspec.lock b/example/pubspec.lock index 3ebb7d1d..c399f40c 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+16" + version: "0.1.1+18" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/lib/src/icons.dart b/lib/src/assets/icons.dart similarity index 100% rename from lib/src/icons.dart rename to lib/src/assets/icons.dart diff --git a/lib/src/components/accordion.dart b/lib/src/components/accordion/accordion.dart similarity index 99% rename from lib/src/components/accordion.dart rename to lib/src/components/accordion/accordion.dart index 7c22121d..50407788 100644 --- a/lib/src/components/accordion.dart +++ b/lib/src/components/accordion/accordion.dart @@ -1,6 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// Component [ZetaAccordion] class ZetaAccordion extends StatelessWidget { diff --git a/lib/src/components/avatar.dart b/lib/src/components/avatars/avatar.dart similarity index 99% rename from lib/src/components/avatar.dart rename to lib/src/components/avatars/avatar.dart index 2eae9b55..1c6f2fbb 100644 --- a/lib/src/components/avatar.dart +++ b/lib/src/components/avatars/avatar.dart @@ -1,7 +1,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// [ZetaAvatar] type enum ZetaAvatarType { diff --git a/lib/src/components/badge.dart b/lib/src/components/badges/badge.dart similarity index 98% rename from lib/src/components/badge.dart rename to lib/src/components/badges/badge.dart index 3e563dcc..1b8efa2b 100644 --- a/lib/src/components/badge.dart +++ b/lib/src/components/badges/badge.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///Zeta Badge class ZetaBadge extends StatelessWidget { diff --git a/lib/src/components/indicator.dart b/lib/src/components/badges/indicator.dart similarity index 99% rename from lib/src/components/indicator.dart rename to lib/src/components/badges/indicator.dart index 4f83669e..f28b1fb8 100644 --- a/lib/src/components/indicator.dart +++ b/lib/src/components/badges/indicator.dart @@ -1,6 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// [ZetaIndicator] type enum ZetaIndicatorType { diff --git a/lib/src/components/priority_pill.dart b/lib/src/components/badges/priority_pill.dart similarity index 98% rename from lib/src/components/priority_pill.dart rename to lib/src/components/badges/priority_pill.dart index 49e24f31..581a710a 100644 --- a/lib/src/components/priority_pill.dart +++ b/lib/src/components/badges/priority_pill.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///Zeta Priority Pill class ZetaPriorityPill extends StatelessWidget { diff --git a/lib/src/components/status_label.dart b/lib/src/components/badges/status_label.dart similarity index 99% rename from lib/src/components/status_label.dart rename to lib/src/components/badges/status_label.dart index 3172ffa7..dcc82bcb 100644 --- a/lib/src/components/status_label.dart +++ b/lib/src/components/badges/status_label.dart @@ -1,6 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///Zeta Status Label class ZetaStatusLabel extends StatelessWidget { diff --git a/lib/src/components/tag.dart b/lib/src/components/badges/tag.dart similarity index 99% rename from lib/src/components/tag.dart rename to lib/src/components/badges/tag.dart index 07f3aee0..41aebb31 100644 --- a/lib/src/components/tag.dart +++ b/lib/src/components/badges/tag.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///Tag Direction options enum ZetaTagDirection { diff --git a/lib/src/components/workcloud_indicator.dart b/lib/src/components/badges/workcloud_indicator.dart similarity index 99% rename from lib/src/components/workcloud_indicator.dart rename to lib/src/components/badges/workcloud_indicator.dart index 2d9b81b6..1e3599ab 100644 --- a/lib/src/components/workcloud_indicator.dart +++ b/lib/src/components/badges/workcloud_indicator.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///Indicator Type enum ZetaWorkcloudIndicatorType { diff --git a/lib/src/components/in_page_banner.dart b/lib/src/components/banners/in_page_banner.dart similarity index 98% rename from lib/src/components/in_page_banner.dart rename to lib/src/components/banners/in_page_banner.dart index f5e9af7b..f744501e 100644 --- a/lib/src/components/in_page_banner.dart +++ b/lib/src/components/banners/in_page_banner.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///[ZetaInPageBanner] button attributes class ZetaPageBannerButton { @@ -43,7 +43,7 @@ class ZetaInPageBanner extends StatelessWidget { ///Defaults to 'neutral' final WidgetSeverity severity; - ///Determines if the banner hase icon for closing + ///Determines if the banner has icon for closing ///Defaults to true final bool showIconClose; diff --git a/lib/src/components/system_banner.dart b/lib/src/components/banners/system_banner.dart similarity index 99% rename from lib/src/components/system_banner.dart rename to lib/src/components/banners/system_banner.dart index 96fda9ed..323a8d50 100644 --- a/lib/src/components/system_banner.dart +++ b/lib/src/components/banners/system_banner.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// [ZetaSystemBanner] type enum ZetaSystemBannerType { diff --git a/lib/src/components/bottom_sheet.dart b/lib/src/components/bottom sheets/bottom_sheet.dart similarity index 98% rename from lib/src/components/bottom_sheet.dart rename to lib/src/components/bottom sheets/bottom_sheet.dart index e57adb04..b0e473d7 100644 --- a/lib/src/components/bottom_sheet.dart +++ b/lib/src/components/bottom sheets/bottom_sheet.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// Component [ZetaBottomSheet] class ZetaBottomSheet extends StatelessWidget { diff --git a/lib/src/components/menu_items.dart b/lib/src/components/bottom sheets/menu_items.dart similarity index 99% rename from lib/src/components/menu_items.dart rename to lib/src/components/bottom sheets/menu_items.dart index b2a53978..4a5adf15 100644 --- a/lib/src/components/menu_items.dart +++ b/lib/src/components/bottom sheets/menu_items.dart @@ -1,6 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// The type of the [ZetaMenuItem] enum ZetaMenuItemType { diff --git a/lib/src/components/button.dart b/lib/src/components/buttons/button.dart similarity index 99% rename from lib/src/components/button.dart rename to lib/src/components/buttons/button.dart index f0fd45f4..fa54ec4d 100644 --- a/lib/src/components/button.dart +++ b/lib/src/components/buttons/button.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///Colors for the [ZetaButton] widget class ZetaButtonColors extends ZetaWidgetColor { diff --git a/lib/src/components/fab.dart b/lib/src/components/buttons/fab.dart similarity index 99% rename from lib/src/components/fab.dart rename to lib/src/components/buttons/fab.dart index 71ef2c67..32944796 100644 --- a/lib/src/components/fab.dart +++ b/lib/src/components/buttons/fab.dart @@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///Defines the color of the floating action button enum ZetaFabType { diff --git a/lib/src/components/checkbox.dart b/lib/src/components/checkbox/checkbox.dart similarity index 99% rename from lib/src/components/checkbox.dart rename to lib/src/components/checkbox/checkbox.dart index 1bfb4b55..5d0f7d5b 100644 --- a/lib/src/components/checkbox.dart +++ b/lib/src/components/checkbox/checkbox.dart @@ -1,6 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///Zeta Checkbox class ZetaCheckbox extends StatelessWidget { diff --git a/lib/src/components/chip.dart b/lib/src/components/chip/chip.dart similarity index 99% rename from lib/src/components/chip.dart rename to lib/src/components/chip/chip.dart index 590e9781..71086b89 100644 --- a/lib/src/components/chip.dart +++ b/lib/src/components/chip/chip.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// The type of [ZetaChip] enum ZetaChipType { diff --git a/lib/src/components/password_input.dart b/lib/src/components/password/password_input.dart similarity index 99% rename from lib/src/components/password_input.dart rename to lib/src/components/password/password_input.dart index d784e35c..e2d8f3dc 100644 --- a/lib/src/components/password_input.dart +++ b/lib/src/components/password/password_input.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; ///Extension for password visibility state handling extension on ValueNotifier { diff --git a/lib/src/components/grid.dart b/lib/src/legacy/grid.dart similarity index 99% rename from lib/src/components/grid.dart rename to lib/src/legacy/grid.dart index d41cce71..ea0a8636 100644 --- a/lib/src/components/grid.dart +++ b/lib/src/legacy/grid.dart @@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../theme/breakpoints.dart'; -import '../tokens.dart' as tokens; +import '../theme/tokens.dart' as tokens; import '../utils/extensions.dart'; diff --git a/lib/src/components/spacing.dart b/lib/src/legacy/spacing.dart similarity index 99% rename from lib/src/components/spacing.dart rename to lib/src/legacy/spacing.dart index f58138d6..04d27ba8 100644 --- a/lib/src/components/spacing.dart +++ b/lib/src/legacy/spacing.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; -import '../tokens.dart'; +import '../theme/tokens.dart'; /// Spacing types for [ZetaSpacing]. diff --git a/lib/src/components/text.dart b/lib/src/legacy/text.dart similarity index 99% rename from lib/src/components/text.dart rename to lib/src/legacy/text.dart index 172488ef..34b68d86 100644 --- a/lib/src/components/text.dart +++ b/lib/src/legacy/text.dart @@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../zeta_flutter.dart'; -import '../tokens.dart' as tokens; +import '../theme/tokens.dart' as tokens; /// {@template zeta-component-text} /// ZetaText component. diff --git a/lib/src/tokens.dart b/lib/src/theme/tokens.dart similarity index 98% rename from lib/src/tokens.dart rename to lib/src/theme/tokens.dart index fdfe7837..b6943026 100644 --- a/lib/src/tokens.dart +++ b/lib/src/theme/tokens.dart @@ -1,4 +1,4 @@ -import '../../zeta_flutter.dart'; +import '../../../zeta_flutter.dart'; /// Tokens that are used for [ZetaSpacing]. /// diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 9f034835..5aaf5ae2 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -1,27 +1,27 @@ /// Zebra Design System (Zeta) - Flutter Component Library library zeta_flutter; -export 'src/components/accordion.dart'; -export 'src/components/avatar.dart'; -export 'src/components/badge.dart'; -export 'src/components/bottom_sheet.dart'; -export 'src/components/button.dart'; -export 'src/components/checkbox.dart'; -export 'src/components/chip.dart'; -export 'src/components/fab.dart'; -export 'src/components/grid.dart'; -export 'src/components/in_page_banner.dart'; -export 'src/components/indicator.dart'; -export 'src/components/menu_items.dart'; -export 'src/components/password_input.dart'; -export 'src/components/priority_pill.dart'; -export 'src/components/spacing.dart'; -export 'src/components/status_label.dart'; -export 'src/components/system_banner.dart'; -export 'src/components/tag.dart'; -export 'src/components/text.dart'; -export 'src/components/workcloud_indicator.dart'; -export 'src/icons.dart'; +export 'src/assets/icons.dart'; +export 'src/components/accordion/accordion.dart'; +export 'src/components/avatars/avatar.dart'; +export 'src/components/badges/badge.dart'; +export 'src/components/badges/indicator.dart'; +export 'src/components/badges/priority_pill.dart'; +export 'src/components/badges/status_label.dart'; +export 'src/components/badges/tag.dart'; +export 'src/components/badges/workcloud_indicator.dart'; +export 'src/components/banners/in_page_banner.dart'; +export 'src/components/banners/system_banner.dart'; +export 'src/components/bottom sheets/bottom_sheet.dart'; +export 'src/components/bottom sheets/menu_items.dart'; +export 'src/components/buttons/button.dart'; +export 'src/components/buttons/fab.dart'; +export 'src/components/checkbox/checkbox.dart'; +export 'src/components/chip/chip.dart'; +export 'src/components/password/password_input.dart'; +export 'src/legacy/grid.dart'; +export 'src/legacy/spacing.dart'; +export 'src/legacy/text.dart'; export 'src/theme/color_extensions.dart'; export 'src/theme/color_scheme.dart'; export 'src/theme/color_swatch.dart'; @@ -29,7 +29,7 @@ export 'src/theme/constants.dart'; export 'src/theme/contrast.dart'; export 'src/theme/theme_data.dart'; export 'src/theme/theme_service.dart'; -export 'src/tokens.dart'; +export 'src/theme/tokens.dart'; export 'src/utils/enums.dart'; export 'src/utils/extensions.dart'; export 'src/zeta.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 08429bf0..7d3efbd6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+18 +version: 0.1.1+19 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. From 6ae1269422180bbf2ecbfd05814969bfcbb725f1 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Wed, 17 Jan 2024 15:36:01 +0000 Subject: [PATCH 29/41] feat: Update text styles to match latest designs (#50) https://jira.zebra.com/browse/UX-808 --------- Co-authored-by: github-actions --- CHANGELOG.md | 11 +- example/lib/home.dart | 47 +- example/lib/main.dart | 2 + example/lib/pages/button_example.dart | 8 +- example/lib/pages/checkbox_example.dart | 8 +- example/lib/pages/color_example.dart | 13 +- example/lib/pages/grid_example.dart | 5 +- example/lib/pages/icons_example.dart | 4 +- example/lib/pages/in_page_banner_example.dart | 2 +- .../lib/pages/theme/typography_example.dart | 115 +++ example/lib/pages/theme_constrast_switch.dart | 5 +- example/lib/pages/typography_example.dart | 188 ----- example/lib/widgets.dart | 50 +- example/macos/Podfile.lock | 15 + example/pubspec.lock | 2 +- example/test/checkbox_test.dart | 2 +- example/test/status_label_test.dart | 2 +- example/test/test_components.dart | 4 +- example/test/typography_test.dart | 73 +- .../components/color_widgetbook.dart | 5 +- .../components/in_page_banner_widgetbook.dart | 2 +- .../components/typography_widgetbook.dart | 114 --- .../theme/typography_widgetbook.dart | 46 ++ example/widgetbook/widgetbook.dart | 11 +- lib/src/components/accordion/accordion.dart | 11 +- lib/src/components/badges/badge.dart | 2 +- lib/src/components/badges/indicator.dart | 20 +- lib/src/components/badges/priority_pill.dart | 4 +- lib/src/components/badges/status_label.dart | 2 +- lib/src/components/badges/tag.dart | 2 +- .../badges/workcloud_indicator.dart | 6 +- .../components/banners/in_page_banner.dart | 4 +- lib/src/components/banners/system_banner.dart | 8 +- .../bottom sheets/bottom_sheet.dart | 6 +- .../components/bottom sheets/menu_items.dart | 3 +- lib/src/components/buttons/button.dart | 2 +- lib/src/components/buttons/fab.dart | 3 +- lib/src/components/checkbox/checkbox.dart | 10 +- lib/src/components/chip/chip.dart | 4 +- .../components/password/password_input.dart | 10 +- lib/src/legacy/text.dart | 771 ------------------ lib/src/theme/tokens.dart | 19 - lib/src/theme/typography.dart | 132 +++ lib/zeta_flutter.dart | 2 +- pubspec.yaml | 2 +- 45 files changed, 458 insertions(+), 1299 deletions(-) create mode 100644 example/lib/pages/theme/typography_example.dart delete mode 100644 example/lib/pages/typography_example.dart delete mode 100644 example/widgetbook/components/typography_widgetbook.dart create mode 100644 example/widgetbook/theme/typography_widgetbook.dart delete mode 100644 lib/src/legacy/text.dart create mode 100644 lib/src/theme/typography.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 53179ba5..db175629 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [0.1.1+20] - 2024-01-17 +### :sparkles: New Features +- [`35d1d7e`](https://github.com/zebratechnologies/zeta-flutter/commit/35d1d7eed509d4b89593c17e2a48a4a2c79a6ce4) - Update text styles to match latest designs *(PR [#50](https://github.com/zebratechnologies/zeta-flutter/pull/50) by [@thelukewalton](https://github.com/thelukewalton))* + +### :wrench: Chores +- [`6787220`](https://github.com/zebratechnologies/zeta-flutter/commit/67872203f0dc96de02e6945f0ac4409f95872262) - Organize ilb/ to match web *(PR [#49](https://github.com/zebratechnologies/zeta-flutter/pull/49) by [@thelukewalton](https://github.com/thelukewalton))* + + ## [0.1.1+19] - 2024-01-17 ### :wrench: Chores - [`d1c0125`](https://github.com/zebratechnologies/zeta-flutter/commit/d1c012523e16ebbf3f38c7028598660cfc7b7ea9) - Organize ilb/ to match web *(PR [#49](https://github.com/zebratechnologies/zeta-flutter/pull/49) by [@thelukewalton](https://github.com/thelukewalton))* @@ -1715,4 +1723,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+15]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+14...0.1.1+15 [0.1.1+16]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+15...0.1.1+16 [0.1.1+18]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+17...0.1.1+18 -[0.1.1+19]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+18...0.1.1+19 \ No newline at end of file +[0.1.1+19]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+18...0.1.1+19 +[0.1.1+20]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+19...0.1.1+20 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index fe96c7d7..02559dbf 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -25,7 +25,7 @@ import 'package:zeta_example/pages/indicator_example.dart'; import 'package:zeta_example/pages/spacing_example.dart'; import 'package:zeta_example/pages/status_label_example.dart'; import 'package:zeta_example/pages/tag_example.dart'; -import 'package:zeta_example/pages/typography_example.dart'; +import 'package:zeta_example/pages/theme/typography_example.dart'; import 'package:zeta_example/pages/workcloud_indicator_example.dart'; import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; @@ -41,7 +41,6 @@ class Component { final List components = [ Component(GridExample.name, (context) => const GridExample()), Component(SpacingExample.name, (context) => const SpacingExample()), - Component(TypographyExample.name, (context) => const TypographyExample()), Component(ColorExample.name, (context) => const ColorExample()), Component(AvatarExample.name, (context) => const AvatarExample()), Component(IconsExample.name, (context) => const IconsExample()), @@ -75,6 +74,10 @@ final List components = [ Component(BottomSheetExample.name, (context) => const BottomSheetExample()), ]; +final List theme = [ + Component(TypographyExample.name, (context) => TypographyExample()), +]; + class Home extends StatefulWidget { const Home({super.key}); @@ -89,17 +92,13 @@ final GoRouter router = GoRouter( name: 'Home', builder: (_, __) => const Home(), routes: [ - ...components.map( + ...[...components, ...theme].map( (e) => GoRoute( path: e.name, name: e.name, builder: (_, __) => e.pageBuilder.call(_), routes: e.children - .map((f) => GoRoute( - path: f.name, - name: f.name, - builder: (_, __) => f.pageBuilder(_), - )) + .map((f) => GoRoute(path: f.name, name: f.name, builder: (_, __) => f.pageBuilder(_))) .toList(), ), ) @@ -111,18 +110,30 @@ final GoRouter router = GoRouter( class _HomeState extends State { @override Widget build(BuildContext context) { - final items = components..sort((a, b) => a.name.compareTo(b.name)); + final _components = components..sort((a, b) => a.name.compareTo(b.name)); + final _theme = theme..sort((a, b) => a.name.compareTo(b.name)); + return ExampleScaffold( name: 'Zeta', - child: ListView.builder( - padding: EdgeInsets.all(Dimensions.s), - itemCount: items.length, - itemBuilder: (context, index) { - return ListTile( - title: ZetaText(items[index].name), - onTap: () => context.go('/${items[index].name}'), - ); - }, + 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(), + ), + ], + ), ), ); } diff --git a/example/lib/main.dart b/example/lib/main.dart index aa8df680..596eed2e 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -53,12 +53,14 @@ class ZetaExample extends StatelessWidget { fontFamily: themeData.fontFamily, scaffoldBackgroundColor: light.background, colorScheme: light, + textTheme: zetaTextTheme, ), darkTheme: ThemeData( useMaterial3: true, fontFamily: themeData.fontFamily, scaffoldBackgroundColor: dark.background, colorScheme: dark, + textTheme: zetaTextTheme, ), ); }, diff --git a/example/lib/pages/button_example.dart b/example/lib/pages/button_example.dart index 1e8baead..3316eff4 100644 --- a/example/lib/pages/button_example.dart +++ b/example/lib/pages/button_example.dart @@ -73,20 +73,22 @@ Widget sharpButtonsExample(BuildExampleButtonColors colors) => Column( List _getZetaButtonExampleRows(String label, ZetaButtonColors colors, {IconData? icon, ZetaButtonType buttonType = ZetaButtonType.filled, BorderType border = BorderType.rounded}) { return [ - Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text('Large $label', style: ZetaText.zetaTitleLarge)]), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [Text('Large $label', style: ZetaTextStyles.titleLarge)]), Divider(color: Colors.transparent), _getRow(buttonType, ZetaWidgetSize.large, colors, border: border, icon: icon), Divider(color: Colors.transparent), _getRow(buttonType, ZetaWidgetSize.large, colors, isDisabled: true, border: border, icon: icon), Row( mainAxisAlignment: MainAxisAlignment.center, - children: [Padding(padding: EdgeInsets.all(10), child: Text('Medium $label', style: ZetaText.zetaTitleLarge))], + children: [Padding(padding: EdgeInsets.all(10), child: Text('Medium $label', style: ZetaTextStyles.titleLarge))], ), _getRow(buttonType, ZetaWidgetSize.medium, colors, border: border, icon: icon), _getRow(buttonType, ZetaWidgetSize.medium, colors, isDisabled: true, border: border, icon: icon), Row( mainAxisAlignment: MainAxisAlignment.center, - children: [Padding(padding: EdgeInsets.all(10), child: Text('Small $label', style: ZetaText.zetaTitleLarge))], + children: [Padding(padding: EdgeInsets.all(10), child: Text('Small $label', style: ZetaTextStyles.titleLarge))], ), _getRow(buttonType, ZetaWidgetSize.small, colors, border: border, icon: icon), _getRow(buttonType, ZetaWidgetSize.small, colors, isDisabled: true, border: border, icon: icon), diff --git a/example/lib/pages/checkbox_example.dart b/example/lib/pages/checkbox_example.dart index a82ca833..a5c93cdd 100644 --- a/example/lib/pages/checkbox_example.dart +++ b/example/lib/pages/checkbox_example.dart @@ -36,13 +36,13 @@ class _CheckBoxExampleState extends State { ) ], ), - Row(children: [Text('Sharp Checkbox Enabled', style: ZetaText.zetaTitleLarge)]), + Row(children: [Text('Sharp Checkbox Enabled', style: ZetaTextStyles.titleLarge)]), getCheckBoxRow(isEnabled: true), - Row(children: [Text('Sharp Checkbox Disabled', style: ZetaText.zetaTitleLarge)]), + Row(children: [Text('Sharp Checkbox Disabled', style: ZetaTextStyles.titleLarge)]), getCheckBoxRow(isEnabled: false), - Row(children: [Text('Rounded Checkbox Enabled', style: ZetaText.zetaTitleLarge)]), + Row(children: [Text('Rounded Checkbox Enabled', style: ZetaTextStyles.titleLarge)]), getCheckBoxRow(isEnabled: true, isSharp: false), - Row(children: [Text('Rounded Checkbox Disabled', style: ZetaText.zetaTitleLarge)]), + Row(children: [Text('Rounded Checkbox Disabled', style: ZetaTextStyles.titleLarge)]), getCheckBoxRow(isEnabled: false, isSharp: false), ], ), diff --git a/example/lib/pages/color_example.dart b/example/lib/pages/color_example.dart index 1093e8bf..df538581 100644 --- a/example/lib/pages/color_example.dart +++ b/example/lib/pages/color_example.dart @@ -147,7 +147,7 @@ class _ColorExampleState extends State { MyRow(children: backdrop, title: 'Backdrop colors'), MyRow(children: primaries, title: 'Primary colors'), MyRow(children: alerts, title: 'Alert colors'), - Row(children: [ZetaText.displayMedium('Full color swatches')]).squish(Dimensions.x8), + Row(children: [Text('Full color swatches', style: ZetaTextStyles.displayMedium)]).squish(Dimensions.x8), ...swatches.entries.map( (value) => Row( children: List.generate(10, (index) => 100 - (10 * index)) @@ -162,7 +162,7 @@ class _ColorExampleState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ DefaultTextStyle( - style: ZetaText.zetaBodyMedium + style: ZetaTextStyles.bodyMedium .copyWith(color: calculateTextColor(value.value[e] ?? Colors.white)), child: Column( children: [ @@ -185,7 +185,8 @@ class _ColorExampleState extends State { child: const Text('Toggle generated colors').square(Dimensions.s), ).square(Dimensions.s), if (showGeneratedColors) - Row(children: [ZetaText.displayMedium('Generated color swatches')]).squish(Dimensions.x8), + Row(children: [Text('Generated color swatches', style: ZetaTextStyles.displayMedium)]) + .squish(Dimensions.x8), if (showGeneratedColors) ...generatedSwatches.entries.map( (value) => Row( @@ -203,7 +204,7 @@ class _ColorExampleState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ DefaultTextStyle( - style: ZetaText.zetaBodyMedium + style: ZetaTextStyles.bodyMedium .copyWith(color: calculateTextColor(value.value[e] ?? Colors.white)), child: Column( children: [ @@ -251,7 +252,7 @@ class MyRow extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ZetaText.labelLarge(title, textColor: Zeta.of(context).colors.textDefault), + Text(title, style: ZetaTextStyles.labelLarge), Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, @@ -268,7 +269,7 @@ class MyRow extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ DefaultTextStyle( - style: ZetaText.zetaBodyMedium.copyWith(color: calculateTextColor(e.value)), + style: ZetaTextStyles.bodyMedium.copyWith(color: calculateTextColor(e.value)), child: Column( children: [ Text(e.key), diff --git a/example/lib/pages/grid_example.dart b/example/lib/pages/grid_example.dart index fd10ed3d..44e81314 100644 --- a/example/lib/pages/grid_example.dart +++ b/example/lib/pages/grid_example.dart @@ -105,7 +105,10 @@ class GridItem extends StatelessWidget { decoration: BoxDecoration(border: Border.all(color: colors.blue.border), color: colors.blue.surface), child: Padding( padding: const EdgeInsets.only(left: 8), - child: ZetaText.bodyLarge(label, textColor: colors.blue.text), + child: Text( + label, + style: ZetaTextStyles.bodyLarge.apply(color: colors.blue.text), + ), ), ); } diff --git a/example/lib/pages/icons_example.dart b/example/lib/pages/icons_example.dart index 756bdd1d..2e82bc9b 100644 --- a/example/lib/pages/icons_example.dart +++ b/example/lib/pages/icons_example.dart @@ -25,7 +25,7 @@ class _IconsExampleState extends State { padding: EdgeInsets.all(Dimensions.s), child: Column( children: [ - ZetaText.bodyLarge('Round'), + Text('Round', style: ZetaTextStyles.bodyLarge), Wrap( spacing: 8, runSpacing: 8, @@ -518,7 +518,7 @@ class _IconsExampleState extends State { ], ), const SizedBox(height: 20), - ZetaText.bodyLarge('Sharp'), + Text('Sharp', style: ZetaTextStyles.bodyLarge), Wrap( spacing: 8, runSpacing: 8, diff --git a/example/lib/pages/in_page_banner_example.dart b/example/lib/pages/in_page_banner_example.dart index ad297f59..819e3665 100644 --- a/example/lib/pages/in_page_banner_example.dart +++ b/example/lib/pages/in_page_banner_example.dart @@ -58,7 +58,7 @@ class InPageBannerExample extends StatelessWidget { Widget _getTitle(String title) => Container( height: 50, - child: Center(child: Text(title, style: ZetaText.zetaTitleLarge)), + child: Center(child: Text(title, style: ZetaTextStyles.titleLarge)), ); } diff --git a/example/lib/pages/theme/typography_example.dart b/example/lib/pages/theme/typography_example.dart new file mode 100644 index 00000000..854b3f70 --- /dev/null +++ b/example/lib/pages/theme/typography_example.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +const String exampleText = 'The quick brown fox jumps over the lazy dog.'; + +class TypographyExample extends StatelessWidget { + static const String name = 'Typography'; + + const TypographyExample({super.key}); + + @override + Widget build(BuildContext context) { + final dedicatedSizes = [ + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.displayLarge), + code: "Text('...', style: ZetaTextStyles.displayLarge)", + title: 'Display Large', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.displayMedium), + code: "Text('...', style: ZetaTextStyles.displayMedium)", + title: 'Display Medium', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.displaySmall), + code: "Text('...', style: ZetaTextStyles.displaySmall)", + title: 'Display Small', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.heading1), + code: "Text('...', style: ZetaTextStyles.heading1)", + title: 'Heading 1', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.heading2), + code: "Text('...', style: ZetaTextStyles.heading2)", + title: 'Heading 2', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.heading3), + code: "Text('...', style: ZetaTextStyles.heading3)", + title: 'Heading 3', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.titleLarge), + code: "Text('...', style: ZetaTextStyles.titleLarge)", + title: 'Title Large', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.titleMedium), + code: "Text('...', style: ZetaTextStyles.titleMedium)", + title: 'Title Medium', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.titleSmall), + code: "Text('...', style: ZetaTextStyles.titleSmall)", + title: 'Title Small', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.bodyLarge), + code: "Text('...', style: ZetaTextStyles.titleLarge)", + title: 'Body Large', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.bodyMedium), + code: "Text('...', style: ZetaTextStyles.titleMedium)", + title: 'Body Medium', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.bodySmall), + code: "Text('...', style: ZetaTextStyles.titleSmall)", + title: 'Body Small', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.labelLarge), + code: "Text('...', style: ZetaTextStyles.labelLarge)", + title: 'Label Large', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.labelMedium), + code: "Text('...', style: ZetaTextStyles.labelMedium)", + title: 'Label Medium', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.labelSmall), + code: "Text('...', style: ZetaTextStyles.labelSmall)", + title: 'Label Small', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.labelIndicator), + code: "Text('...', style: ZetaTextStyles.labelIndicator)", + title: 'Label Indicator', + ), + ExampleModel( + example: Text(exampleText, style: ZetaTextStyles.labelTiny), + code: "Text('...', style: ZetaTextStyles.labelTiny)", + title: 'Label Tiny', + ), + ]; + + return ExampleScaffold( + name: name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ...dedicatedSizes.map(ExampleBuilder.new), + ], + ), + ), + ); + } +} diff --git a/example/lib/pages/theme_constrast_switch.dart b/example/lib/pages/theme_constrast_switch.dart index 2200ddeb..780acd01 100644 --- a/example/lib/pages/theme_constrast_switch.dart +++ b/example/lib/pages/theme_constrast_switch.dart @@ -37,10 +37,9 @@ class ZetaThemeContrastSwitch extends StatelessWidget { child: CircleAvatar( backgroundColor: colors.primary.surface, foregroundColor: colors.primary, - child: ZetaText.bodyMedium( + child: Text( e == ZetaContrast.aa ? 'AA' : 'AAA', - textColor: colors.primary, - fontWeight: FontWeight.w700, + style: ZetaTextStyles.bodyMedium.copyWith(color: colors.primary, fontWeight: FontWeight.w700), ), ), ); diff --git a/example/lib/pages/typography_example.dart b/example/lib/pages/typography_example.dart deleted file mode 100644 index 0ff46d3b..00000000 --- a/example/lib/pages/typography_example.dart +++ /dev/null @@ -1,188 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; -import '../widgets.dart'; - -const String exampleText = 'Lorem ipsum dolor sit amet.'; -const String exampleParagraph = - 'Paragraph: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.'; - -class TypographyExample extends StatelessWidget { - static const String name = 'Typography'; - - const TypographyExample({super.key}); - - static const Map sizes = { - 'x3': Dimensions.x3, - 'x3_5': Dimensions.x3_5, - 'x4': Dimensions.x4, - 'x5': Dimensions.x5, - 'x6': Dimensions.x6, - 'x7': Dimensions.x7, - 'x8': Dimensions.x8, - 'x9': Dimensions.x9, - 'x10': Dimensions.x10, - 'x11': Dimensions.x11, - 'x12': Dimensions.x12, - 'x13': Dimensions.x13, - }; - static final List universalSizes = sizes.entries.map( - (size) { - return ExampleModel( - example: ZetaText(exampleText, fontSize: size.value), - token: size.value == Dimensions.x3_5 - ? r'$text.zeta.x3_5.x4' - : r'$text.zeta.x' + '${size.value ~/ 4}.x${(size.value + 4) ~/ 4}', - code: "ZetaText('', size: ZetaSpacing.${size.key})", - ); - }, - ).toList(); - - static final dedicatedSizes = [ - ExampleModel( - example: ZetaText.bodySmall(exampleText), - wDescription: ZetaText.bodySmall(exampleParagraph, maxWidth: 66), - code: "ZetaText.bodySmall('')", - token: r'$text.zeta.bodysmall', - ), - ExampleModel( - example: ZetaText.bodyMedium(exampleText), - wDescription: ZetaText.bodyMedium(exampleParagraph, maxWidth: 66), - code: "ZetaText.bodyMedium('')", - token: r'$text.zeta.bodymedium', - ), - ExampleModel( - example: ZetaText.bodyLarge(exampleText), - wDescription: ZetaText.bodyLarge(exampleParagraph, maxWidth: 66), - code: "ZetaText.bodyLarge('')", - token: r'$text.zeta.bodylarge', - ), - ExampleModel( - example: ZetaText.titleSmall(exampleText), - code: "ZetaText.titleSmall('')", - token: r'$text.zeta.titlesmall', - ), - ExampleModel( - example: ZetaText.titleMedium(exampleText), - code: "ZetaText.titleMedium('')", - token: r'$text.zeta.titlemedium', - ), - ExampleModel( - example: ZetaText.titleLarge(exampleText), - code: "ZetaText.titleLarge('')", - token: r'$text.zeta.titlelarge', - ), - ExampleModel( - example: ZetaText.headingSmall(exampleText), - code: "ZetaText.headingSmall('')", - token: r'$text.zeta.headingsmall', - ), - ExampleModel( - example: ZetaText.headingMedium(exampleText), - code: "ZetaText.headingMedium('')", - token: r'$text.zeta.headingmedium', - ), - ExampleModel( - example: ZetaText.headingLarge(exampleText), - code: "ZetaText.headingLarge('')", - token: r'$text.zeta.headinglarge', - ), - ExampleModel( - example: ZetaText.displaySmall(exampleText), - code: "ZetaText.displaySmall('')", - token: r'$text.zeta.displaysmall', - ), - ExampleModel( - example: ZetaText.displayMedium(exampleText), - code: "ZetaText.displayMedium('')", - token: r'$text.zeta.displaymedium', - ), - ExampleModel( - example: ZetaText.displayLarge(exampleText), - code: "ZetaText.displayLarge('')", - token: r'$text.zeta.displaylarge', - ), - ]; - - @override - Widget build(BuildContext context) { - final colors = Zeta.of(context).colors; - - final tokens = [ - const ExampleModel( - example: ZetaText(exampleText), - code: "ZetaText('')", - token: r'$text.zeta', - ), - ExampleModel( - example: ZetaText(exampleText, textColor: colors.textSubtle), - code: "ZetaText('', textColor: ZetaColors.textColorSubtle)", - token: r'$text.zeta.subtle', - ), - const ExampleModel( - example: ZetaText(exampleText, fontWeight: FontWeight.w300), - code: "ZetaText('', fontWeight: FontWeight.w300)", - token: r'$text.zeta.300', - ), - const ExampleModel( - example: ZetaText(exampleText, fontWeight: FontWeight.w500), - code: "ZetaText('', fontWeight: FontWeight.w500)", - token: r'$text.zeta.500', - ), - const ExampleModel( - example: ZetaText(exampleText, fontStyle: FontStyle.italic), - code: "ZetaText('', fontStyle: FontStyle.italic)", - token: r'$text.zeta.italics', - ), - const ExampleModel( - code: "ZetaText('', uppercase: true)", - token: r'$text.zeta.caps', - example: ZetaText(exampleText, upperCase: true), - ), - const ExampleModel( - example: ZetaText(exampleText, decoration: TextDecoration.underline), - code: "ZetaText('', decoration: TextDecoration.underline)", - token: r'$text.zeta.underline', - ), - const ExampleModel( - code: "ZetaText('', textDirection: TextDirection.rtl)", - token: r'$text.zeta.direction', - example: ZetaText(exampleText, textDirection: TextDirection.rtl), - ), - const ExampleModel( - code: "ZetaText('', first: true)", - token: r'$text.zeta.first', - example: ZetaText(exampleText, first: true), - ), - const ExampleModel( - code: "ZetaText('', last: true)", - token: r'$text.zeta.last', - example: ZetaText(exampleText, last: true), - ), - const ExampleModel( - code: "ZetaText('', resetHeight: true)", - token: r'$text.zeta.reset', - example: ZetaText(exampleText, resetHeight: true), - ), - ]; - - return ExampleScaffold( - name: name, - child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ZetaText.headingLarge('Text').inline(Dimensions.x10), - ...tokens.map(ExampleBuilder.new), - const Divider().squish(Dimensions.x4), - ZetaText.headingLarge('Universal sizes').inline(Dimensions.x10), - ...universalSizes.map(ExampleBuilder.new), - const Divider().squish(Dimensions.x4), - ZetaText.headingLarge('Dedicated sizes').inline(Dimensions.x10), - ...dedicatedSizes.map(ExampleBuilder.new), - ], - ), - ), - ); - } -} diff --git a/example/lib/widgets.dart b/example/lib/widgets.dart index 9a23b6ef..03ba5073 100644 --- a/example/lib/widgets.dart +++ b/example/lib/widgets.dart @@ -9,16 +9,18 @@ import 'package:zeta_flutter/zeta_flutter.dart'; class ExampleModel { final Widget example; final String code; - final String token; + final String? token; final String? description; final Widget? wDescription; + final String? title; const ExampleModel({ required this.example, - required this.token, required this.code, + this.token, this.description, this.wDescription, + this.title, }); } @@ -32,17 +34,21 @@ class ExampleBuilder extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - height: 7, - width: 7, - decoration: BoxDecoration(color: Theme.of(context).colorScheme.onSurface, shape: BoxShape.circle), - ).squish(Dimensions.x9).inline(Dimensions.x4), + if (model.token != null) + Container( + height: 7, + width: 7, + decoration: BoxDecoration(color: Theme.of(context).colorScheme.onSurface, shape: BoxShape.circle), + ).squish(Dimensions.x9).inline(Dimensions.x4), + if (model.title != null && MediaQuery.of(context).size.width > 767) Expanded(child: Text(model.title!)), Expanded( + flex: 5, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - CodeExample(code: model.token), - if (model.description != null) ZetaText(model.description), + if (model.title != null && MediaQuery.of(context).size.width <= 767) Text(model.title!), + if (model.token != null) CodeExample(code: model.token!), + if (model.description != null) Text(model.description!), if (model.wDescription != null) model.wDescription!, model.example, Container(color: const Color(0xFFF5F5F5)), @@ -79,7 +85,10 @@ class ExampleScaffold extends StatelessWidget { floatingActionButton: floatingActionButton, appBar: AppBar( centerTitle: false, - title: Text(name), + title: Text( + name, + style: ZetaTextStyles.titleMedium, + ), backgroundColor: colors.primary, foregroundColor: colors.onPrimary, actions: [ @@ -118,7 +127,6 @@ class CodeExample extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const FlutterWordMark(), Row(children: [Expanded(child: widget)]), ], ), @@ -129,23 +137,3 @@ class CodeExample extends StatelessWidget { .squish(Dimensions.x4); } } - -class FlutterWordMark extends StatelessWidget { - final String text; - final EdgeInsets padding; - - const FlutterWordMark({ - this.text = 'Flutter', - this.padding = const EdgeInsets.symmetric(horizontal: Dimensions.x5, vertical: Dimensions.x2), - super.key, - }); - - @override - Widget build(BuildContext context) { - return Container( - color: Zeta.of(context).colors.borderSubtle, - padding: padding, - child: ZetaText(text), - ); - } -} diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index b99453dc..2b66f435 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -1,16 +1,27 @@ PODS: - FlutterMacOS (1.0.0) + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS + - sqflite (0.0.2): + - FlutterMacOS + - FMDB (>= 2.7.5) DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) + - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) + +SPEC REPOS: + trunk: + - FMDB EXTERNAL SOURCES: FlutterMacOS: @@ -19,11 +30,15 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin shared_preferences_foundation: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin + sqflite: + :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 + sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 diff --git a/example/pubspec.lock b/example/pubspec.lock index c399f40c..9acae33d 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+18" + version: "0.1.1+19" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/checkbox_test.dart b/example/test/checkbox_test.dart index bc10b708..882cfa3a 100644 --- a/example/test/checkbox_test.dart +++ b/example/test/checkbox_test.dart @@ -59,7 +59,7 @@ class TestWidgetCB extends StatelessWidget { return MaterialApp( theme: ThemeData( fontFamily: theme.fontFamily, - textTheme: ZetaText.textTheme, + textTheme: zetaTextTheme, ), home: Scaffold( body: widget, diff --git a/example/test/status_label_test.dart b/example/test/status_label_test.dart index 9eeaca88..2536a149 100644 --- a/example/test/status_label_test.dart +++ b/example/test/status_label_test.dart @@ -42,7 +42,7 @@ class TestWidgetStatusLabel extends StatelessWidget { return MaterialApp( theme: ThemeData( fontFamily: theme.fontFamily, - textTheme: ZetaText.textTheme, + textTheme: zetaTextTheme, ), home: Scaffold( body: widget, diff --git a/example/test/test_components.dart b/example/test/test_components.dart index 117e5717..29ac4a03 100644 --- a/example/test/test_components.dart +++ b/example/test/test_components.dart @@ -19,12 +19,12 @@ class TestWidget extends StatelessWidget { theme: ThemeData( fontFamily: theme.fontFamily, colorScheme: theme.colorsLight.toScheme(), - textTheme: ZetaText.textTheme, + textTheme: zetaTextTheme, ), darkTheme: ThemeData( fontFamily: theme.fontFamily, colorScheme: theme.colorsDark.toScheme(), - textTheme: ZetaText.textTheme, + textTheme: zetaTextTheme, ), home: Scaffold( body: SizedBox( diff --git a/example/test/typography_test.dart b/example/test/typography_test.dart index b20074f0..6eec19ef 100644 --- a/example/test/typography_test.dart +++ b/example/test/typography_test.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:zeta_example/pages/typography_example.dart'; +import 'package:zeta_example/pages/theme/typography_example.dart'; + import 'package:zeta_flutter/zeta_flutter.dart'; import 'test_components.dart'; @@ -18,23 +19,14 @@ void main() { builder: (context) { return Column( children: [ - const ZetaText(exampleText, key: key1), - ZetaText( + const Text(exampleText, key: key1), + Text(exampleText, style: ZetaTextStyles.bodyMedium, key: key2), + Text(exampleText, style: ZetaTextStyles.displayLarge, key: key3), + Text( exampleText, - maxWidth: 66, - decoration: TextDecoration.underline, - key: key2, - upperCase: true, - fontSize: 100, - fontStyle: FontStyle.italic, - fontWeight: FontWeight.w500, - textColor: Zeta.of(context).colors.textSubtle, - textDirection: TextDirection.rtl, - first: true, - last: true, + style: TextStyle(fontSize: 52, fontWeight: FontWeight.w300, height: 64 / 52), + key: key4, ), - ZetaText(exampleText, style: ZetaText.zetaHeadingLarge, key: key3), - ZetaText.headingLarge(exampleText, key: key4), ], ); }, @@ -56,46 +48,19 @@ void main() { final InlineSpan text4 = (find.descendant(of: zetaText4, matching: find.byType(RichText)).evaluate().first.widget as RichText).text; - final Padding padding1 = - find.descendant(of: zetaText1, matching: find.byType(Padding)).evaluate().first.widget as Padding; - final Padding padding2 = - find.descendant(of: zetaText2, matching: find.byType(Padding)).evaluate().first.widget as Padding; + /// Test default in [Text] widget is [ZetaTextStyles.bodyMedium]. + expect(text1.style, text2.style); - final item1Size = tester.getSize(zetaText1); - final item2Size = tester.getSize(zetaText2); + /// Test that [ZetaTextStyles.displayLarge] has not changed. + expect(text3.style, text4.style); - expect(item1Size == item2Size, false); - expect(item2Size.width.floor(), 800); - expect( - TextStyle( - fontSize: text1.style?.fontSize, - height: text1.style?.height, - fontWeight: text1.style?.fontWeight, - ), - ZetaText.zetaBodyMedium, - ); - expect( - TextStyle( - fontSize: text2.style?.fontSize, - height: text2.style?.height, - fontWeight: text2.style?.fontWeight, - ) == - ZetaText.zetaBodyMedium, - false, - ); - expect(text1.style?.fontFamily, 'packages/zeta_flutter/IBMPlexSans'); - expect(text1.style?.color, const Color(0xFF1D1E23)); + /// Test font size of [ZetaTextStyles.bodyMedium] is correct + expect(text1.style!.fontSize, 14); + + /// Test line height of [ZetaTextStyles.bodyMedium] is correct + expect(text1.style!.height, 20 / 14); - expect(text1.style?.decoration, TextDecoration.none); - expect(text1.toPlainText(), exampleText); - expect(text2.toPlainText(), exampleText.toUpperCase()); - expect(text2.style?.decoration, TextDecoration.underline); - expect(text2.style?.fontSize, 100); - expect(text2.style?.fontStyle, FontStyle.italic); - expect(text2.style?.fontWeight, FontWeight.w500); - expect(text2.style?.color, const Color(0xFF545963)); - expect(padding1.padding, Dimensions.x2.squish); - expect(padding2.padding, EdgeInsets.zero); - expect(text3, text4); + /// Test font weight of [ZetaTextStyles.bodyMedium] is correct + expect(text1.style!.fontWeight, FontWeight.w400); }); } diff --git a/example/widgetbook/components/color_widgetbook.dart b/example/widgetbook/components/color_widgetbook.dart index 3c4ef757..ccae7570 100644 --- a/example/widgetbook/components/color_widgetbook.dart +++ b/example/widgetbook/components/color_widgetbook.dart @@ -72,7 +72,8 @@ WidgetbookComponent colorWidgetBook() { MyRow(children: links, title: 'Links'), MyRow(children: backdrop, title: 'Backdrop colors'), MyRow(children: alerts, title: 'Alert colors'), - Row(children: [ZetaText.displayMedium('Full color swatches')]).squish(Dimensions.x8), + Row(children: [Text('Full color swatches', style: ZetaTextStyles.displayMedium)]) + .squish(Dimensions.x8), ...swatches.entries.map( (value) { return Row( @@ -88,7 +89,7 @@ WidgetbookComponent colorWidgetBook() { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ DefaultTextStyle( - style: ZetaText.zetaBodyMedium.copyWith( + style: ZetaTextStyles.bodyMedium.copyWith( color: calculateTextColor(value.value[e] ?? Colors.white), ), child: Column( diff --git a/example/widgetbook/components/in_page_banner_widgetbook.dart b/example/widgetbook/components/in_page_banner_widgetbook.dart index 01e4dab4..b5f69d96 100644 --- a/example/widgetbook/components/in_page_banner_widgetbook.dart +++ b/example/widgetbook/components/in_page_banner_widgetbook.dart @@ -6,7 +6,7 @@ import 'package:zeta_flutter/zeta_flutter.dart'; WidgetbookComponent inPageBannerWidgetBook() { Widget _getTitle(String title) => Container( height: 50, - child: Center(child: Text(title, style: ZetaText.zetaTitleLarge)), + child: Center(child: Text(title, style: ZetaTextStyles.titleLarge)), ); ZetaWidgetColor _getCustomColors() => diff --git a/example/widgetbook/components/typography_widgetbook.dart b/example/widgetbook/components/typography_widgetbook.dart deleted file mode 100644 index d7f5949b..00000000 --- a/example/widgetbook/components/typography_widgetbook.dart +++ /dev/null @@ -1,114 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/typography_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent textWidgetBook() { - final dedicatedSizes = { - 'Body small': ZetaText.zetaBodySmall, - 'Body medium': ZetaText.zetaBodyMedium, - 'Body large': ZetaText.zetaBodyLarge, - 'Headline small': ZetaText.zetaHeadingSmall, - 'Headline medium': ZetaText.zetaHeadingMedium, - 'Headline large': ZetaText.zetaHeadingLarge, - 'Display small': ZetaText.zetaDisplaySmall, - 'Display medium': ZetaText.zetaDisplayMedium, - 'Display large': ZetaText.zetaDisplayLarge, - }; - return WidgetbookComponent( - name: 'Typography', - useCases: [ - WidgetbookUseCase( - name: 'Tokens', - builder: (context) => const _TextWrapper(), - ), - WidgetbookUseCase( - name: 'Universal sizes', - builder: (context) => Container( - color: Theme.of(context).colorScheme.background, - padding: const EdgeInsets.all(Dimensions.l), - child: ZetaText( - exampleText, - fontSize: context.knobs.list( - label: 'Sizes', - labelBuilder: (p0) => p0 == 14 ? 'x3_5' : 'x${p0! ~/ 4}', - options: const [ - Dimensions.x3, - Dimensions.x3_5, - Dimensions.x4, - Dimensions.x5, - Dimensions.x6, - Dimensions.x7, - Dimensions.x8, - Dimensions.x9, - Dimensions.x10, - Dimensions.x11, - Dimensions.x12, - Dimensions.x13, - ], - ), - ), - ), - ), - WidgetbookUseCase( - name: 'Dedicated sizes', - builder: (context) => Container( - color: Theme.of(context).colorScheme.background, - padding: const EdgeInsets.all(Dimensions.l), - child: ZetaText( - exampleText, - style: context.knobs.list( - label: 'Sizes', - labelBuilder: (p0) => dedicatedSizes.entries.firstWhere((element) => element.value == p0).key, - options: dedicatedSizes.values.toList(), - ), - ), - ), - ), - ], - ); -} - -class _TextWrapper extends StatelessWidget { - const _TextWrapper(); - - @override - Widget build(BuildContext context) { - final colors = Zeta.of(context).colors; - return Container( - padding: const EdgeInsets.all(Dimensions.l), - child: ZetaText( - context.knobs.string(label: 'Input text', initialValue: exampleText.split(',').first), - decoration: context.knobs.boolean(label: 'Underline') ? TextDecoration.underline : null, - first: context.knobs.boolean(label: 'First'), - last: context.knobs.boolean(label: 'Last'), - fontStyle: context.knobs.boolean(label: 'Italic') ? FontStyle.italic : null, - fontWeight: context.knobs.list( - label: 'Font Weight', - labelBuilder: (p0) => p0 == FontWeight.w400 - ? 'Default' - : p0 == FontWeight.w300 - ? 'Light' - : 'Medium', - options: const [FontWeight.w400, FontWeight.w300, FontWeight.w500], - ), - resetHeight: context.knobs.boolean(label: 'Reset height'), - textColor: context.knobs.list( - label: 'Text color', - labelBuilder: (p0) => p0?.value == colors.textDefault.value ? 'Default' : 'Subtle', - options: [colors.textDefault, colors.textSubtle], - ), - textDirection: context.knobs.list( - label: 'Text direction', - options: const [ - TextDirection.ltr, - TextDirection.rtl, - ], - ), - upperCase: context.knobs.boolean(label: 'Upper case'), - maxWidth: context.knobs.double.slider(label: 'Width', initialValue: 66, max: 100, min: 10, divisions: 90), - fontSize: context.knobs.double.slider(label: 'Font size', initialValue: 12, divisions: 42, min: 12, max: 96), - ), - ); - } -} diff --git a/example/widgetbook/theme/typography_widgetbook.dart b/example/widgetbook/theme/typography_widgetbook.dart new file mode 100644 index 00000000..21e3a59f --- /dev/null +++ b/example/widgetbook/theme/typography_widgetbook.dart @@ -0,0 +1,46 @@ +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(Dimensions.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 2edb9b64..539859e7 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -19,8 +19,8 @@ import 'components/priority_pill_widgetbook.dart'; import 'components/spacing_widgetbook.dart'; import 'components/status_label_widgetbook.dart'; import 'components/tag_widgetbook.dart'; -import 'components/typography_widgetbook.dart'; import 'components/workcloud_indicator_widgetbook.dart'; +import 'theme/typography_widgetbook.dart'; import 'utils/zebra.dart'; class HotReload extends StatelessWidget { @@ -33,11 +33,10 @@ class HotReload extends StatelessWidget { return Widgetbook.material( directories: [ WidgetbookCategory( - name: 'widgets', + name: 'Components', children: [ gridWidgetBook(), spacingWidgetbook(), - textWidgetBook(), colorWidgetBook(), statusLabelWidgetBook(), tagWidgetBook(), @@ -57,6 +56,12 @@ class HotReload extends StatelessWidget { bottomSheetWidgetBook(), ], ), + WidgetbookCategory( + name: 'Theme', + children: [ + textWidgetBook(), + ], + ), ], addons: [ DeviceFrameAddon( diff --git a/lib/src/components/accordion/accordion.dart b/lib/src/components/accordion/accordion.dart index 50407788..e0d4016a 100644 --- a/lib/src/components/accordion/accordion.dart +++ b/lib/src/components/accordion/accordion.dart @@ -199,10 +199,7 @@ class _ZetaAccordionSectionState extends State with Ticker mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ DefaultTextStyle( - style: TextStyle( - fontSize: 18, - height: 1.33, - fontWeight: FontWeight.w500, + style: ZetaTextStyles.titleMedium.apply( color: _disabled ? zetaColors.textDisabled : zetaColors.textDefault, ), child: Flexible(child: widget.title), @@ -226,11 +223,7 @@ class _ZetaAccordionSectionState extends State with Ticker child: Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), child: DefaultTextStyle( - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: zetaColors.textDefault, - ), + style: ZetaTextStyles.titleSmall, child: widget.body, ), ), diff --git a/lib/src/components/badges/badge.dart b/lib/src/components/badges/badge.dart index 1b8efa2b..ceeabe37 100644 --- a/lib/src/components/badges/badge.dart +++ b/lib/src/components/badges/badge.dart @@ -65,7 +65,7 @@ class ZetaBadge extends StatelessWidget { padding: const EdgeInsets.fromLTRB(4, 2, 4, 2), child: Text( label, - style: ZetaText.zetaLabelSmall.apply(color: _badgeForegroundColor(theme)), + style: ZetaTextStyles.labelSmall.apply(color: _badgeForegroundColor(theme)), overflow: TextOverflow.ellipsis, ), ), diff --git a/lib/src/components/badges/indicator.dart b/lib/src/components/badges/indicator.dart index f28b1fb8..61c4fc31 100644 --- a/lib/src/components/badges/indicator.dart +++ b/lib/src/components/badges/indicator.dart @@ -220,17 +220,12 @@ class _InnerContent extends StatelessWidget { ); case ZetaIndicatorType.notification: final strVal = value == null ? '' : value!.abs().toString(); - final fontSize = _getFontSize(size); + return Center( child: Text( strVal.length > 1 ? '9+' : strVal, textAlign: strVal.length == 1 ? TextAlign.center : TextAlign.right, - style: TextStyle( - fontSize: fontSize, - height: .9, - letterSpacing: -0.5, - color: foregroundColor ?? defaultColor, - ), + style: size == ZetaIndicatorSize.large ? ZetaTextStyles.labelIndicator : ZetaTextStyles.labelTiny, ), ); } @@ -247,17 +242,6 @@ class _InnerContent extends StatelessWidget { } } - double _getFontSize(ZetaIndicatorSize size) { - switch (size) { - case ZetaIndicatorSize.large: - return 12; - case ZetaIndicatorSize.medium: - return 11; - case ZetaIndicatorSize.small: - return 1; - } - } - @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); diff --git a/lib/src/components/badges/priority_pill.dart b/lib/src/components/badges/priority_pill.dart index 581a710a..b52e2b57 100644 --- a/lib/src/components/badges/priority_pill.dart +++ b/lib/src/components/badges/priority_pill.dart @@ -59,7 +59,7 @@ class ZetaPriorityPill extends StatelessWidget { ), child: Text( '$index', - style: ZetaText.zetaTitleSmall.apply(color: theme.colors.white), + style: ZetaTextStyles.bodyMedium.apply(color: theme.colors.white), ), ); } @@ -70,7 +70,7 @@ class ZetaPriorityPill extends StatelessWidget { padding: const EdgeInsets.fromLTRB(8, 4, 8, 4), child: Text( priority, - style: ZetaText.zetaTitleSmall, + style: ZetaTextStyles.bodyMedium, overflow: TextOverflow.ellipsis, ), ), diff --git a/lib/src/components/badges/status_label.dart b/lib/src/components/badges/status_label.dart index dcc82bcb..7faed37c 100644 --- a/lib/src/components/badges/status_label.dart +++ b/lib/src/components/badges/status_label.dart @@ -86,7 +86,7 @@ class ZetaStatusLabel extends StatelessWidget { Flexible( child: Text( label, - style: ZetaText.zetaTitleSmall, + style: ZetaTextStyles.bodyMedium, overflow: TextOverflow.ellipsis, ), ), diff --git a/lib/src/components/badges/tag.dart b/lib/src/components/badges/tag.dart index 41aebb31..d0c5d9a5 100644 --- a/lib/src/components/badges/tag.dart +++ b/lib/src/components/badges/tag.dart @@ -107,7 +107,7 @@ class ZetaTag extends StatelessWidget { ), child: Text( label, - style: ZetaText.zetaBodyMedium, + style: ZetaTextStyles.bodyMedium, overflow: TextOverflow.ellipsis, ), ), diff --git a/lib/src/components/badges/workcloud_indicator.dart b/lib/src/components/badges/workcloud_indicator.dart index 1e3599ab..ba372d09 100644 --- a/lib/src/components/badges/workcloud_indicator.dart +++ b/lib/src/components/badges/workcloud_indicator.dart @@ -105,7 +105,7 @@ class ZetaWorkcloudIndicator extends StatelessWidget { Dimensions.x2, Dimensions.x1, ), - child: Text(labelContent, style: ZetaText.zetaBodyXSmall), + child: Text(labelContent, style: ZetaTextStyles.bodySmall), ), ), ); @@ -262,8 +262,8 @@ class _ZetaWorkcloudIndicatorStyle { } static TextStyle getTextStyle(ZetaWidgetSize size, Zeta theme) { - if (size == ZetaWidgetSize.large) return ZetaText.zetaBodyMedium; - return ZetaText.zetaBodySmall; + if (size == ZetaWidgetSize.large) return ZetaTextStyles.bodyMedium; + return ZetaTextStyles.bodySmall; } static EdgeInsets getEdgeInsets(ZetaWidgetSize size) { diff --git a/lib/src/components/banners/in_page_banner.dart b/lib/src/components/banners/in_page_banner.dart index f744501e..114adfa8 100644 --- a/lib/src/components/banners/in_page_banner.dart +++ b/lib/src/components/banners/in_page_banner.dart @@ -164,7 +164,7 @@ class ZetaInPageBanner extends StatelessWidget { child: Padding( padding: EdgeInsets.only(left: hasTitle ? Dimensions.x7 : Dimensions.x0), child: DefaultTextStyle( - style: ZetaText.zetaBodySmall.apply(color: theme.colors.textDefault), + style: ZetaTextStyles.bodyMedium, child: content, ), ), @@ -187,7 +187,7 @@ class ZetaInPageBanner extends StatelessWidget { Widget _buildTitle() => Flexible( child: Text( title!, - style: ZetaText.zetaTitleMedium, + style: ZetaTextStyles.titleSmall, softWrap: true, overflow: TextOverflow.ellipsis, ), diff --git a/lib/src/components/banners/system_banner.dart b/lib/src/components/banners/system_banner.dart index 323a8d50..f41c95b6 100644 --- a/lib/src/components/banners/system_banner.dart +++ b/lib/src/components/banners/system_banner.dart @@ -76,13 +76,7 @@ class ZetaSystemBanner extends StatelessWidget implements PreferredSizeWidget { leading: leading, automaticallyImplyLeading: automaticallyImplyLeading, title: DefaultTextStyle( - style: TextStyle( - fontSize: 16, - height: 1.5, - fontWeight: FontWeight.w500, - color: foregroundColor, - overflow: TextOverflow.ellipsis, - ), + style: ZetaTextStyles.titleSmall.apply(color: foregroundColor, overflow: TextOverflow.ellipsis), child: titleIcon == null ? title ?? const SizedBox() : Row( diff --git a/lib/src/components/bottom sheets/bottom_sheet.dart b/lib/src/components/bottom sheets/bottom_sheet.dart index b0e473d7..44dfaef8 100644 --- a/lib/src/components/bottom sheets/bottom_sheet.dart +++ b/lib/src/components/bottom sheets/bottom_sheet.dart @@ -66,11 +66,7 @@ class ZetaBottomSheet extends StatelessWidget { alignment: titleAlignment ?? Alignment.center, child: Text( title!, - style: ZetaText.zetaTitleLarge.copyWith( - color: colors.textDefault, - fontSize: 18, - height: 1.33, - ), + style: ZetaTextStyles.titleMedium, ), ), body ?? const SizedBox(), diff --git a/lib/src/components/bottom sheets/menu_items.dart b/lib/src/components/bottom sheets/menu_items.dart index 4a5adf15..211fe89e 100644 --- a/lib/src/components/bottom sheets/menu_items.dart +++ b/lib/src/components/bottom sheets/menu_items.dart @@ -155,9 +155,8 @@ class ZetaMenuItem extends StatelessWidget { } } - static TextStyle _defaultTextStyle(ZetaColors colors, bool disabled) => ZetaText.zetaLabelLarge.copyWith( + static TextStyle _defaultTextStyle(ZetaColors colors, bool disabled) => ZetaTextStyles.labelLarge.apply( color: disabled ? colors.textDisabled : colors.textDefault, - height: 1, ); static IconThemeData _iconThemeData(ZetaColors colors, bool disabled, double size) => IconThemeData( diff --git a/lib/src/components/buttons/button.dart b/lib/src/components/buttons/button.dart index fa54ec4d..8b0dd8a6 100644 --- a/lib/src/components/buttons/button.dart +++ b/lib/src/components/buttons/button.dart @@ -203,7 +203,7 @@ class ZetaButton extends StatelessWidget { BorderRadius _getBorderRadius() => borderType == BorderType.rounded ? BorderRadius.circular(Dimensions.x1) : BorderRadius.zero; - TextStyle _getTextStyle() => size == ZetaWidgetSize.small ? ZetaText.zetaLabelMedium : ZetaText.zetaLabelLarge; + TextStyle _getTextStyle() => size == ZetaWidgetSize.small ? ZetaTextStyles.labelMedium : ZetaTextStyles.labelLarge; double _iconSize() => size == ZetaWidgetSize.small ? Dimensions.x4 : Dimensions.x5; diff --git a/lib/src/components/buttons/fab.dart b/lib/src/components/buttons/fab.dart index 32944796..61f14792 100644 --- a/lib/src/components/buttons/fab.dart +++ b/lib/src/components/buttons/fab.dart @@ -215,8 +215,7 @@ class _ZetaFABState extends State { ? BorderRadius.circular(Dimensions.x2) : BorderRadius.zero; - TextStyle _getTextStyle() => - widget.buttonSize == ZetaFabSize.large ? ZetaText.zetaTitleLarge : ZetaText.zetaTitleMedium; + TextStyle _getTextStyle() => ZetaTextStyles.labelLarge; double _getButtonSize() => widget.buttonSize == ZetaFabSize.small ? Dimensions.x14 : Dimensions.x24; diff --git a/lib/src/components/checkbox/checkbox.dart b/lib/src/components/checkbox/checkbox.dart index 5d0f7d5b..b0acd201 100644 --- a/lib/src/components/checkbox/checkbox.dart +++ b/lib/src/components/checkbox/checkbox.dart @@ -10,7 +10,6 @@ class ZetaCheckbox extends StatelessWidget { required this.onChanged, this.borderType = BorderType.sharp, this.label, - this.labelStyle, this.checkboxSize = const Size(20, 20), this.selectedColor, this.unselectedColor, @@ -36,9 +35,6 @@ class ZetaCheckbox extends StatelessWidget { /// The label displayed next to the checkbox final String? label; - /// Style to use on the label - final TextStyle? labelStyle; - ///Size of the checkbox final Size checkboxSize; @@ -106,10 +102,7 @@ class ZetaCheckbox extends StatelessWidget { Flexible( child: Padding( padding: const EdgeInsets.only(left: Dimensions.s), - child: Text( - label!, - style: labelStyle ?? ZetaText.zetaBodyLarge, - ), + child: Text(label!, style: ZetaTextStyles.bodyLarge), ), ), ], @@ -190,7 +183,6 @@ class ZetaCheckbox extends StatelessWidget { ..add(ObjectFlagProperty>.has('onChanged', onChanged)) ..add(EnumProperty('borderType', borderType)) ..add(StringProperty('label', label)) - ..add(DiagnosticsProperty('labelStyle', labelStyle)) ..add(DiagnosticsProperty('checkboxSize', checkboxSize)) ..add(ColorProperty('selectedColor', selectedColor)) ..add(ColorProperty('unselectedColor', unselectedColor)) diff --git a/lib/src/components/chip/chip.dart b/lib/src/components/chip/chip.dart index 71086b89..80bde652 100644 --- a/lib/src/components/chip/chip.dart +++ b/lib/src/components/chip/chip.dart @@ -104,8 +104,8 @@ class ZetaChip extends StatelessWidget { backgroundColor: bgColor, label: Text(label, textAlign: TextAlign.center), labelStyle: type == ZetaChipType.status - ? ZetaText.zetaBodyXSmall - : ZetaText.zetaBodySmall.apply(color: selected ? colors.textInverse : colors.textDefault), + ? ZetaTextStyles.bodySmall // TODO(thelukewalton): this doesnt match styles on figma. Awaiting design refresh. + : ZetaTextStyles.bodyMedium.apply(color: selected ? colors.textInverse : colors.textDefault), labelPadding: type == ZetaChipType.status ? const EdgeInsets.symmetric(horizontal: 10) : EdgeInsets.fromLTRB( diff --git a/lib/src/components/password/password_input.dart b/lib/src/components/password/password_input.dart index e2d8f3dc..33b81778 100644 --- a/lib/src/components/password/password_input.dart +++ b/lib/src/components/password/password_input.dart @@ -138,7 +138,7 @@ class _ZetaPasswordInputState extends State { Widget _buildLabel() { return Padding( padding: const EdgeInsets.symmetric(vertical: Dimensions.x1), - child: Text(widget.label!, style: ZetaText.zetaBodyMedium), + child: Text(widget.label!, style: ZetaTextStyles.bodyMedium), ); } @@ -208,7 +208,7 @@ class _ZetaPasswordInputState extends State { if (_errorMessage == null && widget.footerText != null) ...[ Text( widget.footerText!, - style: ZetaText.zetaBodySmall.copyWith( + style: ZetaTextStyles.bodySmall.apply( color: widget.enabled ? colors.hintColor : colors.hintDisableColor, ), ), @@ -228,7 +228,7 @@ class _ZetaPasswordInputState extends State { const SizedBox(width: Dimensions.x1), Text( _errorMessage!, - style: ZetaText.zetaBodySmall.copyWith(color: color), + style: ZetaTextStyles.bodySmall.apply(color: color), ), ]; } @@ -268,8 +268,8 @@ class _ZetaPasswordInputState extends State { } TextStyle _getTextStyle() { - if (widget.size == ZetaWidgetSize.small) return ZetaText.zetaBodySmall; - return ZetaText.zetaBodyMedium; + if (widget.size == ZetaWidgetSize.small) return ZetaTextStyles.bodyMedium; + return ZetaTextStyles.bodyLarge; } double _getSuffixIconSize() { diff --git a/lib/src/legacy/text.dart b/lib/src/legacy/text.dart deleted file mode 100644 index 34b68d86..00000000 --- a/lib/src/legacy/text.dart +++ /dev/null @@ -1,771 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -import '../../zeta_flutter.dart'; -import '../theme/tokens.dart' as tokens; - -/// {@template zeta-component-text} -/// ZetaText component. -/// -/// Applies Zeta style to text, including fontFamily, size, lineHeight, spacing and other modifiers. -/// -/// {@endtemplate} -/// See also: -/// * [Text]. -class ZetaText extends StatelessWidget { - /// Constructor for [ZetaText]. - const ZetaText( - this.data, { - this.style, - this.resetHeight = false, - this.textColor, - this.fontSize, - this.maxWidth, - this.fontWeight, - this.fontStyle, - this.upperCase = false, - this.decoration, - this.textDirection = TextDirection.ltr, - this.first = false, - this.last = false, - super.key, - }); - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-body-xs} - ZetaText.bodyXSmall( - this.data, { - this.resetHeight = false, - this.maxWidth, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - super.key, - }) : style = zetaBodyXSmall; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-body-s} - ZetaText.bodySmall( - this.data, { - this.resetHeight = false, - this.maxWidth, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - super.key, - }) : style = zetaBodySmall; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-body-m} - ZetaText.bodyMedium( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaBodyMedium; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-body-l} - ZetaText.bodyLarge( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaBodyLarge; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-label-s} - ZetaText.labelSmall( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - super.key, - this.maxWidth, - }) : style = zetaLabelSmall; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-label-m} - ZetaText.labelMedium( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaLabelMedium; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-label-l} - ZetaText.labelLarge( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaLabelLarge; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-title-s} - ZetaText.titleSmall( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaTitleSmall; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-title-m} - ZetaText.titleMedium( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaTitleMedium; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-title-l} - ZetaText.titleLarge( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaTitleLarge; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-heading-s} - ZetaText.headingSmall( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaHeadingSmall; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-heading-m} - ZetaText.headingMedium( - this.data, { - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.resetHeight = false, - this.maxWidth, - super.key, - }) : style = zetaHeadingMedium; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-heading-l} - ZetaText.headingLarge( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaHeadingLarge; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-display-s} - ZetaText.displaySmall( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaDisplaySmall; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-display-m} - ZetaText.displayMedium( - this.data, { - this.resetHeight = false, - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.maxWidth, - super.key, - }) : style = zetaDisplayMedium; - - /// {@macro zeta-component-text} - /// - /// {@macro zeta-type-display-l} - ZetaText.displayLarge( - this.data, { - this.decoration, - this.fontSize, - this.fontStyle, - this.fontWeight, - this.first = false, - this.last = false, - this.textColor, - this.textDirection = TextDirection.ltr, - this.upperCase = false, - this.resetHeight = false, - this.maxWidth, - super.key, - }) : style = zetaDisplayLarge; - static const double _defaultChMultiplier = 66; - - /// Text styles for Zeta. - /// - /// {@macro zeta-theme} - static TextTheme textTheme = TextTheme( - displayLarge: zetaDisplayLarge, - displayMedium: zetaDisplayMedium, - displaySmall: zetaDisplaySmall, - headlineLarge: zetaHeadingLarge, - headlineMedium: zetaHeadingMedium, - headlineSmall: zetaHeadingSmall, - titleLarge: zetaTitleLarge, - titleMedium: zetaTitleMedium, - titleSmall: zetaTitleSmall, - bodyLarge: zetaBodyLarge, - bodyMedium: zetaBodyMedium, - bodySmall: zetaBodySmall, - labelLarge: zetaLabelLarge, - labelMedium: zetaLabelMedium, - labelSmall: zetaLabelSmall, - ); - - /// Builds text theme for app based on an instance of [ZetaColors]. - static TextTheme themeWithColor(Color color) { - return TextTheme( - displayLarge: zetaDisplayLarge.copyWith(color: color), - displayMedium: zetaDisplayMedium.copyWith(color: color), - displaySmall: zetaDisplaySmall.copyWith(color: color), - headlineLarge: zetaHeadingLarge.copyWith(color: color), - headlineMedium: zetaHeadingMedium.copyWith(color: color), - headlineSmall: zetaHeadingSmall.copyWith(color: color), - titleLarge: zetaTitleLarge.copyWith(color: color), - titleMedium: zetaTitleMedium.copyWith(color: color), - titleSmall: zetaTitleSmall.copyWith(color: color), - bodyLarge: zetaBodyLarge.copyWith(color: color), - bodyMedium: zetaBodyMedium.copyWith(color: color), - bodySmall: zetaBodySmall.copyWith(color: color), - labelLarge: zetaLabelLarge.copyWith(color: color), - labelMedium: zetaLabelMedium.copyWith(color: color), - labelSmall: zetaLabelSmall.copyWith(color: color), - ); - } - - /// {@template zeta-type-body-xs} - /// Smallest body text. - /// - /// Used for UI components and UI content design. - /// - /// {@endtemplate} - static TextStyle zetaBodyXSmall = const TextStyle( - fontSize: tokens.Dimensions.x3, - fontWeight: FontWeight.w400, - height: tokens.Dimensions.x3 / tokens.Dimensions.x4, - ); - - /// {@template zeta-type-body-s} - /// Small body text. - /// - /// Used for UI components and UI content design. - /// - /// See also: - /// * [TextTheme.bodySmall]. - /// {@endtemplate} - static TextStyle zetaBodySmall = const TextStyle( - fontSize: tokens.Dimensions.x3_5, - fontWeight: FontWeight.w400, - height: 18 / 14, - ); - - /// {@template zeta-type-body-m} - /// Medium body text. - /// - /// Used for overall content. - /// - /// See also: - /// * [TextTheme.bodyMedium]. - /// {@endtemplate} - static TextStyle zetaBodyMedium = const TextStyle( - fontSize: tokens.Dimensions.x4, - fontWeight: FontWeight.w400, - height: tokens.Dimensions.x6 / tokens.Dimensions.x4, - ); - - /// {@template zeta-type-body-l} - /// Large body text. - /// - /// Used for UI components and UI content design. - /// - /// See also: - /// * [TextTheme.bodyLarge]. - /// {@endtemplate} - static TextStyle zetaBodyLarge = const TextStyle( - fontSize: tokens.Dimensions.x5, - fontWeight: FontWeight.w400, - height: tokens.Dimensions.x6 / tokens.Dimensions.x5, - ); - - /// {@template zeta-type-label-s} - /// Small label text. - /// - /// Used for UI components and UI content. - /// - /// See also: - /// * [TextTheme.labelSmall]. - /// {@endtemplate} - static TextStyle zetaLabelSmall = const TextStyle( - fontSize: tokens.Dimensions.x3, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x4 / tokens.Dimensions.x3, - ); - - /// {@template zeta-type-label-m} - /// Medium label text. - /// - /// Used for UI components and UI content. - /// - /// See also: - /// * [TextTheme.labelMedium]. - /// {@endtemplate} - static TextStyle zetaLabelMedium = const TextStyle( - fontSize: tokens.Dimensions.x3_5, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x3_5 / tokens.Dimensions.x5, - ); - - /// {@template zeta-type-label-l} - /// Large label text. - /// - /// Used for UI components and UI content. - /// - /// See also: - /// * [TextTheme.labelLarge]. - /// {@endtemplate} - static TextStyle zetaLabelLarge = const TextStyle( - fontSize: tokens.Dimensions.x4, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x4 / tokens.Dimensions.x6, - ); - - /// {@template zeta-type-title-s} - /// Heading 6 / Small title text. - /// - /// Used for UI components and UI content design. - /// - /// See also: - /// * [TextTheme.titleSmall]. - /// {@endtemplate} - static TextStyle zetaTitleSmall = const TextStyle( - fontSize: tokens.Dimensions.x3, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x4 / tokens.Dimensions.x3, - ); - - /// {@template zeta-type-title-m} - /// Heading 5 / Medium title text. - /// - /// Used for UI components and UI content design. - /// - /// See also: - /// * [TextTheme.titleMedium]. - /// {@endtemplate} - static TextStyle zetaTitleMedium = const TextStyle( - fontSize: tokens.Dimensions.x4, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x5 / tokens.Dimensions.x4, - ); - -// TODO(tokens): How to add color and font family here? -// Both can be changed at runtime so can;t be const. -// But also how do we access them without state? - - /// {@template zeta-type-title-l} - /// Heading 4 / Large title text. - /// - /// Used for UI sections and landing pages. - /// - /// See also: - /// * [TextTheme.titleLarge]. - /// {@endtemplate} - static TextStyle zetaTitleLarge = const TextStyle( - fontSize: tokens.Dimensions.x5, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x4 / tokens.Dimensions.x5, - ); - - /// {@template zeta-type-heading-s} - /// Heading 3 text. - /// - /// Used for UI sections and landing pages. - /// - /// See also: - /// * [TextTheme.headlineSmall]. - /// {@endtemplate} - static TextStyle zetaHeadingSmall = const TextStyle( - fontSize: tokens.Dimensions.x6, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x7 / tokens.Dimensions.x6, - ); - - /// {@template zeta-type-heading-m} - /// Heading 2 text. - /// - /// Used for UI sections and landing pages. - /// - /// See also: - /// * [TextTheme.headlineMedium]. - /// {@endtemplate} - static TextStyle zetaHeadingMedium = const TextStyle( - fontSize: tokens.Dimensions.x7, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x8 / tokens.Dimensions.x7, - ); - - /// {@template zeta-type-heading-l} - /// Heading 1 text. - /// - /// Used for UI sections and landing pages. - /// See also: - /// * [TextTheme.headlineLarge]. - /// {@endtemplate} - static TextStyle zetaHeadingLarge = const TextStyle( - fontSize: tokens.Dimensions.x8, - fontWeight: FontWeight.w500, - height: tokens.Dimensions.x9 / tokens.Dimensions.x8, - ); - - /// {@template zeta-type-display-s} - /// Small display text. - /// - /// Used for landing page intros and sections. - /// - /// See also: - /// * [TextTheme.displaySmall]. - /// {@endtemplate} - static TextStyle zetaDisplaySmall = zetaHeadingSmall; - - /// {@template zeta-type-display-m} - /// Medium display text. - /// - /// Used for landing page intros and sections. - /// - /// See also: - /// * [TextTheme.displayMedium]. - /// {@endtemplate} - static TextStyle zetaDisplayMedium = zetaHeadingMedium; - - /// {@template zeta-type-display-l} - /// Large display text. - /// - /// Used for landing page intros. - /// See also: - /// * [TextTheme.displayLarge]. - /// {@endtemplate} - static TextStyle zetaDisplayLarge = zetaHeadingLarge; - - /// Gets approximate char width based on width of O in IBM Plex Sans - /// - /// Only works for IBM Plex. - static double _ch({double multiplier = _defaultChMultiplier, TextStyle? style}) { - final setStyle = style ?? zetaBodyMedium; - const plexCh = 0.6; - - return multiplier * plexCh * (setStyle.fontSize ?? tokens.Dimensions.x3); - } - - /// The text to be displayed. - /// - /// See also: - /// * [Text.data]. - final String? data; - - /// The style applied to the text. - /// - /// Defaults to [zetaBodyMedium]. - /// - /// See also: - /// * [Text.style]. - final TextStyle? style; - - /// Sets text color. - /// - /// See also: - /// * [TextStyle.color]. - final Color? textColor; - - /// Max width of Text box using [_ch]. Not measured in dp / px. - /// - /// [_ch] approximates width of a character using O as basis, so a maxWidth of 60 theoretically returns a max width containing 60 characters. - /// - /// Only works with 'IBM Plex Sans'. - final double? maxWidth; - - /// Font size override. - /// - /// {@template zeta-text-override} - /// Optional as this should be set using [style]. - /// {@endtemplate} - /// See also: - /// * [TextStyle.fontSize]. - final double? fontSize; - - /// Font weight override. - /// - /// {@macro zeta-text-override} - /// - /// See also: - /// * [TextStyle.fontWeight]. - final FontWeight? fontWeight; - - /// Font style override, used to set text to _italic_. - /// - /// - /// - /// See also: - /// * [TextStyle.fontStyle]. - /// * [FontStyle.italic]. - final FontStyle? fontStyle; - - /// Sets all text to uppercase. - /// - /// See also: - /// * [String.toUpperCase]. - final bool upperCase; - - /// Decoration override, used to apply decorations such as underline. - /// - /// See also: - /// * [TextDecoration.underline]. - /// * [TextDecoration]. - final TextDecoration? decoration; - - /// Text direction, used to set text to either Left to Right or Right to Left. - /// - /// See also: - /// * [TextDirection.values]. - final TextDirection textDirection; - - /// Sets padding top to 0. - /// - /// Set to true when this text is first in a list. - final bool first; - - /// Sets padding bottom to 0. - /// - /// Set to true when this text is last in a list. - final bool last; - - /// Sets the line height to 1 and spacing to 0. - /// - /// Defaults to false. - final bool resetHeight; - - EdgeInsets get _padding { - if (resetHeight || (first && last)) return tokens.Dimensions.x0.squish; - - return EdgeInsets.only( - top: first ? tokens.Dimensions.x0 : tokens.Dimensions.x2, - bottom: last ? tokens.Dimensions.x0 : tokens.Dimensions.x2, - ); - } - - double? get _fontSize { - if (fontSize == null) return null; - if (fontSize == tokens.Dimensions.x3_5) { - return tokens.Dimensions.x4 / tokens.Dimensions.x3_5; - } - - return ((fontSize ?? 1) + tokens.Dimensions.x1) / (fontSize ?? 1); - } - - @override - Widget build(BuildContext context) { - TextStyle thisStyle = (style ?? ZetaText.zetaBodyMedium).copyWith( - fontSize: style?.fontSize, - fontWeight: style?.fontWeight, - height: style?.height, - ); - - String data = this.data ?? ''; - final Color color = textColor ?? Zeta.of(context).colors.textDefault; - - thisStyle = thisStyle.copyWith( - fontSize: fontSize ?? thisStyle.fontSize ?? tokens.Typography.defaultTextSize, - height: _fontSize, - fontWeight: fontWeight, - decoration: decoration ?? TextDecoration.none, - fontStyle: fontStyle, - color: color, - ); - - if (resetHeight) thisStyle = thisStyle.copyWith(height: 1); - if (upperCase) data = data.toUpperCase(); - - return Padding( - padding: _padding, - child: maxWidth == null - ? Text(data, style: thisStyle, textDirection: textDirection) - : Align( - alignment: textDirection == TextDirection.rtl ? Alignment.centerRight : Alignment.centerLeft, - child: SizedBox( - width: maxWidth == null ? null : _ch(multiplier: maxWidth ?? 0, style: thisStyle), - child: Text(data, style: thisStyle, textDirection: textDirection), - ), - ), - ); - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(StringProperty('data', data)) - ..add(DiagnosticsProperty('style', style)) - ..add(ColorProperty('textColor', textColor)) - ..add(DoubleProperty('maxWidth', maxWidth)) - ..add(DoubleProperty('fontSize', fontSize)) - ..add(DiagnosticsProperty('fontWeight', fontWeight)) - ..add(EnumProperty('fontStyle', fontStyle)) - ..add(DiagnosticsProperty('upperCase', upperCase)) - ..add(DiagnosticsProperty('decoration', decoration)) - ..add(EnumProperty('textDirection', textDirection)) - ..add(DiagnosticsProperty('first', first)) - ..add(DiagnosticsProperty('last', last)) - ..add(DiagnosticsProperty('resetHeight', resetHeight)); - } -} - -/// Extension to add Zeta's extra small text size. -extension XSmall on TextTheme { - /// Smallest body text size. - TextStyle? get bodyXSmall { - return ZetaText.zetaBodyXSmall; - } -} diff --git a/lib/src/theme/tokens.dart b/lib/src/theme/tokens.dart index b6943026..196a91c9 100644 --- a/lib/src/theme/tokens.dart +++ b/lib/src/theme/tokens.dart @@ -92,25 +92,6 @@ class Dimensions { static const double xxxl = spacingBaseMultiplier * 24; } -/// Tokens that are used for [ZetaText]. -class Typography { - /// Font family used across Zeta. - /// - /// Zeta library contains IBM Plex Sans with latin script. - /// In the case of non-latin languages, this can be overridden: - /// - /// Default text size. - /// - /// Defaults to [Dimensions.s]. - static const double defaultTextSize = Dimensions.s; - - /// Base text color. - // static const Color text = Color(0xFF1D1E23); - /// Subtle text color. - // static const Color subtleText = Color(0xFF545963); - // TODO(tokens): Work out how to do tokens properly -} - /// Tokens that are used for [ZetaGrid]. class Grid { /// Maximum number of cols that can be displayed. diff --git a/lib/src/theme/typography.dart b/lib/src/theme/typography.dart new file mode 100644 index 00000000..62857bbe --- /dev/null +++ b/lib/src/theme/typography.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import '../../zeta_flutter.dart'; + +/// Typography in Zeta style. +/// +/// We have decided to adopt IBM Plex Sans typeface for our digital solutions. +/// This new typeface is clean, distinctive and designed for digital world use cases. +/// The typeface is free and available in multiple languages, making it ideal for localization. +/// More info can be found at: www.ibm.com/plex +class ZetaTextStyles { + /// Largest of the display styles. + /// + /// {@template zeta-text-display} + /// As the largest text on the screen, display styles are reserved for short, + /// important text or numerals. They work best on large screens. + /// {@endtemplate} + static const TextStyle displayLarge = TextStyle(fontSize: 52, fontWeight: FontWeight.w300, height: 64 / 52); + + /// Middle size of the display styles. + /// + /// {@macro zeta-text-display} + static const TextStyle displayMedium = TextStyle(fontSize: 42, fontWeight: FontWeight.w300, height: 56 / 42); + + /// Smallest of the display styles. + /// + /// {@macro zeta-text-display} + static const TextStyle displaySmall = TextStyle(fontSize: 36, fontWeight: FontWeight.w300, height: 48 / 36); + + /// Largest of the headline styles. + /// + ///{@template zeta-text-headline} + /// Headline styles are smaller than display styles. They're best-suited for + /// short, high-emphasis text on smaller screens. + /// {@endtemplate} + static const TextStyle heading1 = TextStyle(fontSize: 32, fontWeight: FontWeight.w500, height: 40 / 32); + + /// Middle size of the headline styles. + /// + /// {@macro zeta-text-headline} + static const TextStyle heading2 = TextStyle(fontSize: 28, fontWeight: FontWeight.w500, height: 32 / 28); + + /// Smallest of the headline styles. + /// + /// {@macro zeta-text-headline} + static const TextStyle heading3 = TextStyle(fontSize: 24, fontWeight: FontWeight.w500, height: 32 / 24); + + /// Largest of the title styles. + /// + /// {@template zeta-text-title} + /// Titles are smaller than headline styles and should be used for shorter, + /// medium-emphasis text. + /// {@endtemplate} + static const TextStyle titleLarge = TextStyle(fontSize: 32, fontWeight: FontWeight.w500, height: 20 / 28); + + /// Middle size of the title styles. + /// + /// {@macro zeta-text-title} + static const TextStyle titleMedium = TextStyle(fontSize: 18, fontWeight: FontWeight.w500, height: 24 / 18); + + /// Smallest of the title styles. + /// + /// {@macro zeta-text-title} + static const TextStyle titleSmall = TextStyle(fontSize: 16, fontWeight: FontWeight.w500, height: 24 / 16); + + /// Largest of the body styles. + /// + /// {@template zeta-text-body} + /// Body styles are used for longer passages of text. + /// {@endtemplate} + static const TextStyle bodyLarge = TextStyle(fontSize: 16, fontWeight: FontWeight.w400, height: 16 / 24); + + /// Middle size of the body styles. + /// + /// {@macro zeta-text-body} + /// + /// The default Text style for [Zeta]. + static const TextStyle bodyMedium = TextStyle(fontSize: 14, fontWeight: FontWeight.w400, height: 20 / 14); + + /// Smallest of the body styles. + /// + /// {@macro zeta-text-body} + static const TextStyle bodySmall = TextStyle(fontSize: 12, fontWeight: FontWeight.w400, height: 16 / 12); + + /// Largest of the label styles. + /// + /// {@template zeta-text-label} + /// Label styles are smaller, utilitarian styles, used for areas of the UI + /// such as text inside of components or very small supporting text in the + /// content body, like captions. + /// {@endtemplate} + /// + /// Used for text on [ZetaButton]. + static const TextStyle labelLarge = TextStyle(fontSize: 16, fontWeight: FontWeight.w500, height: 24 / 16); + + /// Middle size of the label styles. + /// + /// {@macro zeta-text-label} + static const TextStyle labelMedium = TextStyle(fontSize: 14, fontWeight: FontWeight.w500, height: 20 / 14); + + /// Small size of the label styles. + /// + /// {@macro zeta-text-label} + static const TextStyle labelSmall = TextStyle(fontSize: 12, fontWeight: FontWeight.w500, height: 16 / 12); + + /// Label text style used specifically for Indicator. + /// {@macro zeta-text-label} + static const TextStyle labelIndicator = TextStyle(fontSize: 12, fontWeight: FontWeight.w500, height: 14 / 12); + + /// Smallest of the label styles. + /// + /// {@macro zeta-text-label} + static const TextStyle labelTiny = TextStyle(fontSize: 11, fontWeight: FontWeight.w500, height: 14 / 11); +} + +/// [ZetaTextStyles] combined into a [TextTheme]. +const TextTheme zetaTextTheme = TextTheme( + displayLarge: ZetaTextStyles.displayLarge, + displayMedium: ZetaTextStyles.displayMedium, + displaySmall: ZetaTextStyles.displaySmall, + headlineLarge: ZetaTextStyles.heading1, + headlineMedium: ZetaTextStyles.heading2, + headlineSmall: ZetaTextStyles.heading3, + titleLarge: ZetaTextStyles.titleLarge, + titleMedium: ZetaTextStyles.titleMedium, + titleSmall: ZetaTextStyles.titleSmall, + bodyLarge: ZetaTextStyles.bodyLarge, + bodyMedium: ZetaTextStyles.bodyMedium, + bodySmall: ZetaTextStyles.bodySmall, + labelLarge: ZetaTextStyles.labelLarge, + labelMedium: ZetaTextStyles.labelMedium, + labelSmall: ZetaTextStyles.labelSmall, +); diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 5aaf5ae2..9fc701d1 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -21,7 +21,6 @@ export 'src/components/chip/chip.dart'; export 'src/components/password/password_input.dart'; export 'src/legacy/grid.dart'; export 'src/legacy/spacing.dart'; -export 'src/legacy/text.dart'; export 'src/theme/color_extensions.dart'; export 'src/theme/color_scheme.dart'; export 'src/theme/color_swatch.dart'; @@ -30,6 +29,7 @@ export 'src/theme/contrast.dart'; export 'src/theme/theme_data.dart'; export 'src/theme/theme_service.dart'; export 'src/theme/tokens.dart'; +export 'src/theme/typography.dart'; export 'src/utils/enums.dart'; export 'src/utils/extensions.dart'; export 'src/zeta.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 7d3efbd6..46b7fb8c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+19 +version: 0.1.1+20 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. From 7b543ac7b92dc53a866af4de313c36b5728e912e Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 18 Jan 2024 10:34:37 +0000 Subject: [PATCH 30/41] feat: Remove legacy code (#51) BREAKING CHANGE: Removed ZetaGrid and ZetaSpacing components, renamed widget padding extensions https://jira.zebra.com/browse/UX-910 Remove ZetaGrid, ZetaSpacing and ZetaText widgets as these are no longer part of the library. Functionality is retained in some cases (text styles, padding extensions) but widgets themselves are removed. --------- Co-authored-by: github-actions --- CHANGELOG.md | 9 +- example/lib/home.dart | 4 - example/lib/pages/color_example.dart | 9 +- example/lib/pages/grid_example.dart | 115 ----------- example/lib/pages/spacing_example.dart | 132 ------------ example/lib/widgets.dart | 8 +- example/pubspec.lock | 2 +- example/test/grid_test.dart | 42 ---- example/test/spacing_test.dart | 188 ----------------- .../components/color_widgetbook.dart | 2 +- .../components/grid_widgetbook.dart | 84 -------- .../components/spacing_widgetbook.dart | 119 ----------- example/widgetbook/widgetbook.dart | 4 - lib/src/components/badges/indicator.dart | 4 +- .../badges/workcloud_indicator.dart | 4 +- .../components/banners/in_page_banner.dart | 2 +- lib/src/legacy/grid.dart | 156 -------------- lib/src/legacy/spacing.dart | 191 ------------------ lib/src/theme/tokens.dart | 27 +-- lib/src/utils/extensions.dart | 30 +++ lib/zeta_flutter.dart | 2 - pubspec.yaml | 2 +- 22 files changed, 58 insertions(+), 1078 deletions(-) delete mode 100644 example/lib/pages/grid_example.dart delete mode 100644 example/lib/pages/spacing_example.dart delete mode 100644 example/test/grid_test.dart delete mode 100644 example/test/spacing_test.dart delete mode 100644 example/widgetbook/components/grid_widgetbook.dart delete mode 100644 example/widgetbook/components/spacing_widgetbook.dart delete mode 100644 lib/src/legacy/grid.dart delete mode 100644 lib/src/legacy/spacing.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index db175629..74a3d00c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [0.1.1+21] - 2024-01-18 +### :sparkles: New Features +- [`6ae1269`](https://github.com/zebratechnologies/zeta-flutter/commit/6ae1269422180bbf2ecbfd05814969bfcbb725f1) - Update text styles to match latest designs *(PR [#50](https://github.com/zebratechnologies/zeta-flutter/pull/50) by [@thelukewalton](https://github.com/thelukewalton))* +- [`977d7e6`](https://github.com/zebratechnologies/zeta-flutter/commit/977d7e6f7cb0c2b67085ab40f5cf1d410e5680c8) - Remove legacy code *(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))* + + ## [0.1.1+20] - 2024-01-17 ### :sparkles: New Features - [`35d1d7e`](https://github.com/zebratechnologies/zeta-flutter/commit/35d1d7eed509d4b89593c17e2a48a4a2c79a6ce4) - Update text styles to match latest designs *(PR [#50](https://github.com/zebratechnologies/zeta-flutter/pull/50) by [@thelukewalton](https://github.com/thelukewalton))* @@ -1724,4 +1730,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+16]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+15...0.1.1+16 [0.1.1+18]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+17...0.1.1+18 [0.1.1+19]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+18...0.1.1+19 -[0.1.1+20]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+19...0.1.1+20 \ No newline at end of file +[0.1.1+20]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+19...0.1.1+20 +[0.1.1+21]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+20...0.1.1+21 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 02559dbf..4fb9360d 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -14,7 +14,6 @@ import 'package:zeta_example/pages/color_example.dart'; import 'package:zeta_example/pages/checkbox_example.dart'; import 'package:zeta_example/pages/fab_example/fab_example.dart'; import 'package:zeta_example/pages/fab_example/primary_fab.dart'; -import 'package:zeta_example/pages/grid_example.dart'; import 'package:zeta_example/pages/chip_example.dart'; import 'package:zeta_example/pages/menu_items_example.dart'; import 'package:zeta_example/pages/in_page_banner_example.dart'; @@ -22,7 +21,6 @@ import 'package:zeta_example/pages/password_input_example.dart'; import 'package:zeta_example/pages/priority_pill_example.dart'; import 'package:zeta_example/pages/icons_example.dart'; import 'package:zeta_example/pages/indicator_example.dart'; -import 'package:zeta_example/pages/spacing_example.dart'; import 'package:zeta_example/pages/status_label_example.dart'; import 'package:zeta_example/pages/tag_example.dart'; import 'package:zeta_example/pages/theme/typography_example.dart'; @@ -39,8 +37,6 @@ class Component { } final List components = [ - Component(GridExample.name, (context) => const GridExample()), - Component(SpacingExample.name, (context) => const SpacingExample()), Component(ColorExample.name, (context) => const ColorExample()), Component(AvatarExample.name, (context) => const AvatarExample()), Component(IconsExample.name, (context) => const IconsExample()), diff --git a/example/lib/pages/color_example.dart b/example/lib/pages/color_example.dart index df538581..23b6fe6c 100644 --- a/example/lib/pages/color_example.dart +++ b/example/lib/pages/color_example.dart @@ -147,7 +147,8 @@ class _ColorExampleState extends State { MyRow(children: backdrop, title: 'Backdrop colors'), MyRow(children: primaries, title: 'Primary colors'), MyRow(children: alerts, title: 'Alert colors'), - Row(children: [Text('Full color swatches', style: ZetaTextStyles.displayMedium)]).squish(Dimensions.x8), + Row(children: [Text('Full color swatches', style: ZetaTextStyles.displayMedium)]) + .paddingVertical(Dimensions.x8), ...swatches.entries.map( (value) => Row( children: List.generate(10, (index) => 100 - (10 * index)) @@ -182,11 +183,11 @@ class _ColorExampleState extends State { ), ElevatedButton( onPressed: () => setState(() => showGeneratedColors = !showGeneratedColors), - child: const Text('Toggle generated colors').square(Dimensions.s), - ).square(Dimensions.s), + child: const Text('Toggle generated colors').paddingAll(Dimensions.s), + ).paddingAll(Dimensions.s), if (showGeneratedColors) Row(children: [Text('Generated color swatches', style: ZetaTextStyles.displayMedium)]) - .squish(Dimensions.x8), + .paddingVertical(Dimensions.x8), if (showGeneratedColors) ...generatedSwatches.entries.map( (value) => Row( diff --git a/example/lib/pages/grid_example.dart b/example/lib/pages/grid_example.dart deleted file mode 100644 index 44e81314..00000000 --- a/example/lib/pages/grid_example.dart +++ /dev/null @@ -1,115 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class GridExample extends StatelessWidget { - static const String name = 'Grid'; - - static const List symmetrical = [null, 2, 4, 8, 16]; - static const List noGaps = [false, true]; - static const List asymmetrical = [11, 10, 9, 8, 7, 5, 4, 3, 2, 1]; - - const GridExample({super.key}); - - @override - Widget build(BuildContext context) { - final List gridItems = List.generate(20, (index) => GridItem(label: (index + 1).toString())); - - final List examples = [ - ...symmetrical - .map( - (col) => noGaps.map( - (noGaps) => ExampleModel( - example: ZetaGrid( - col: col ?? 12, - noGaps: noGaps, - children: gridItems.getRange(0, (col ?? 12).toInt()).toList(), - ), - token: - r'$grid.zeta' + (col != null && col != 0 ? '.${col.toInt()}col' : '') + (noGaps ? '.nogaps' : ''), - code: - 'ZetaGrid(${col != null ? 'col:${col.toInt()}' : ''}${col != null && noGaps ? ', ' : ''}${noGaps ? 'noGaps: true' : ''}${col != null || noGaps ? ', ' : ''}children:[])', - ), - ), - ) - .expand((element) => element), - ...asymmetrical - .map( - (col) => noGaps.map( - (noGaps) => ExampleModel( - example: ZetaGrid( - asymmetricWeight: col.toInt(), - noGaps: noGaps, - children: gridItems.getRange(0, 12).toList(), - ), - token: r'$grid.zeta' + ('.${col.toInt()}to${(12 - col).toInt()}') + (noGaps ? '.nogaps' : ''), - code: 'ZetaGrid(${'asymmetricWeight:${col.toInt()}'}${noGaps ? ', noGaps: true' : ''}, children:[])', - ), - ), - ) - .expand((element) => element), - ...noGaps.map( - (noGaps) => ExampleModel( - example: Column( - children: [ - ZetaGrid( - noGaps: noGaps, - col: 8, - hybrid: true, - children: const [ - GridItem(width: 120), - Flexible(fit: FlexFit.tight, child: GridItem()), - GridItem(width: 80), - Flexible(fit: FlexFit.tight, flex: 2, child: GridItem()), - GridItem(width: 76), - Flexible(fit: FlexFit.tight, child: GridItem()), - Flexible(fit: FlexFit.tight, flex: 3, child: GridItem()), - GridItem(width: 40), - ], - ), - ], - ), - token: r'$grid.zeta.120px.1fr.80px.2fr.76px.1fr.3fr.40px' + (noGaps ? '.nogaps' : ''), - code: - 'ZetaGrid(\n col: 8,\n hybrid: true,\n ${noGaps ? 'noGaps: true,\n ' : ''}children:[\n GridItem(width: 120),\n Flexible(fit: FlexFit.tight, child: GridItem()),\n GridItem(width: 80),\n Flexible(fit: FlexFit.tight, flex: 2, child: GridItem()),\n GridItem(width: 76),\n Flexible(fit: FlexFit.tight, child: GridItem()),\n Flexible(fit: FlexFit.tight, flex: 3, child: GridItem()),\n GridItem(width: 40),\n ],\n)', - ), - ) - ]; - - return ExampleScaffold( - name: name, - child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [...examples.map(ExampleBuilder.new)], - ), - ), - ); - } -} - -class GridItem extends StatelessWidget { - final String label; - final double? width; - - const GridItem({this.label = '', this.width, super.key}); - - @override - Widget build(BuildContext context) { - final colors = Zeta.of(context).colors; - return Container( - height: 80, - width: width, - decoration: BoxDecoration(border: Border.all(color: colors.blue.border), color: colors.blue.surface), - child: Padding( - padding: const EdgeInsets.only(left: 8), - child: Text( - label, - style: ZetaTextStyles.bodyLarge.apply(color: colors.blue.text), - ), - ), - ); - } -} diff --git a/example/lib/pages/spacing_example.dart b/example/lib/pages/spacing_example.dart deleted file mode 100644 index ca7a82ce..00000000 --- a/example/lib/pages/spacing_example.dart +++ /dev/null @@ -1,132 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class _SizeEx { - final String name; - final double? value; - - const _SizeEx({required this.name, required this.value}); -} - -class _TypeEx { - final String name; - final ZetaSpacingType? value; - final String description; - - const _TypeEx({required this.name, required this.value, required this.description}); -} - -class SpacingExample extends StatelessWidget { - static const String name = 'Spacing'; - - const SpacingExample({super.key}); - - static const List<_SizeEx> _sizes = [ - _SizeEx(name: '', value: null), - _SizeEx(name: 'x1', value: Dimensions.x1), - _SizeEx(name: 'xxs', value: Dimensions.xxs), - _SizeEx(name: 'x2', value: Dimensions.x2), - _SizeEx(name: 'xs', value: Dimensions.xs), - _SizeEx(name: 'x3', value: Dimensions.x3), - _SizeEx(name: 's', value: Dimensions.s), - _SizeEx(name: 'x4', value: Dimensions.x4), - _SizeEx(name: 'b', value: Dimensions.b), - _SizeEx(name: 'x5', value: Dimensions.x5), - _SizeEx(name: 'x6', value: Dimensions.x6), - _SizeEx(name: 'm', value: Dimensions.m), - _SizeEx(name: 'x7', value: Dimensions.x7), - _SizeEx(name: 'x8', value: Dimensions.x8), - _SizeEx(name: 'l', value: Dimensions.l), - _SizeEx(name: 'x9', value: Dimensions.x9), - _SizeEx(name: 'x10', value: Dimensions.x10), - _SizeEx(name: 'x11', value: Dimensions.x11), - _SizeEx(name: 'x12', value: Dimensions.x12), - _SizeEx(name: 'x16', value: Dimensions.x16), - _SizeEx(name: 'xl', value: Dimensions.xl), - _SizeEx(name: 'x20', value: Dimensions.x20), - _SizeEx(name: 'xxl', value: Dimensions.xxl), - _SizeEx(name: 'x24', value: Dimensions.x24), - _SizeEx(name: 'xxxl', value: Dimensions.xxxl), - ]; - - static const List<_TypeEx> _types = [ - _TypeEx(name: '', value: null, description: 'Adds {0}rem either or both margin and padding.'), - _TypeEx(name: 'square', value: ZetaSpacingType.square, description: 'Adds {0}rem padding.'), - _TypeEx(name: 'squish', value: ZetaSpacingType.squish, description: 'Adds {0}rem top and bottom padding.'), - _TypeEx(name: 'inline', value: ZetaSpacingType.inline, description: 'Adds {0}rem left and right padding.'), - _TypeEx(name: 'inline.start', value: ZetaSpacingType.inlineStart, description: 'Adds {0}rem start padding.'), - _TypeEx(name: 'inline.end', value: ZetaSpacingType.inlineEnd, description: 'Adds {0}rem end padding.'), - _TypeEx(name: 'stack', value: ZetaSpacingType.stack, description: 'Adds {0}rem bottom padding.'), - ]; - - static final List _x = _sizes - .map((size) { - final x = _types.map((type) { - return ExampleModel( - token: r'$spacing.zeta' + - (type.value != null ? '.${type.name}' : '') + - (size.value != null ? '.${size.name}' : ''), - example: _SpaceExample(size: size.value ?? 0, type: type.value ?? ZetaSpacingType.square), - description: type.description.replaceAll('{0}', size.value == null ? '0' : (size.value! ~/ 4).toString()), - code: - 'ZetaSpacing${type.value != null ? '.${type.name}' : ''}(child${size.value != null ? ', size: ZetaSpacing.${size.name}' : ''})', - ); - }); - return [...x, null]; - }) - .expand((element) => element) - .toList(); - - @override - Widget build(BuildContext context) { - return ExampleScaffold( - name: name, - child: ListView.builder( - padding: EdgeInsets.all(Dimensions.s), - itemCount: _x.length, - itemBuilder: (context, index) { - final e = _x[index]; - return e == null ? const Divider() : ExampleBuilder(e); - }, - ), - ); - } -} - -class _SpaceExample extends StatelessWidget { - final double size; - final ZetaSpacingType type; - - const _SpaceExample({required this.size, required this.type}); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: ColoredBox( - color: Zeta.of(context).colors.blue.shade20, - child: ZetaSpacing(const SpacingItem(), size: size, type: type), - ), - ), - ], - ); - } -} - -class SpacingItem extends StatelessWidget { - const SpacingItem({super.key}); - - @override - Widget build(BuildContext context) { - return DecoratedBox( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - border: Border.all(color: const Color(0xFFdddddd)), - ), - child: const Text('Text with some spacing'), - ); - } -} diff --git a/example/lib/widgets.dart b/example/lib/widgets.dart index 03ba5073..9cc7199b 100644 --- a/example/lib/widgets.dart +++ b/example/lib/widgets.dart @@ -39,7 +39,7 @@ class ExampleBuilder extends StatelessWidget { height: 7, width: 7, decoration: BoxDecoration(color: Theme.of(context).colorScheme.onSurface, shape: BoxShape.circle), - ).squish(Dimensions.x9).inline(Dimensions.x4), + ).paddingVertical(Dimensions.x9).paddingHorizontal(Dimensions.x4), if (model.title != null && MediaQuery.of(context).size.width > 767) Expanded(child: Text(model.title!)), Expanded( flex: 5, @@ -56,7 +56,7 @@ class ExampleBuilder extends StatelessWidget { ], ), ), - const SizedBox(height: 7, width: 7).squish(Dimensions.x9).inline(Dimensions.x4), + const SizedBox(height: 7, width: 7).paddingVertical(Dimensions.x9).paddingHorizontal(Dimensions.x4), ], ); } @@ -116,7 +116,7 @@ class CodeExample extends StatelessWidget { final colors = Zeta.of(context).colors; final widget = Container( color: colors.surfaceDisabled, - padding: Dimensions.x4.square, + padding: EdgeInsets.all(Dimensions.x4), child: Text(code, style: GoogleFonts.ibmPlexMono(color: colors.textDefault)), ); @@ -134,6 +134,6 @@ class CodeExample extends StatelessWidget { ], ) : widget) - .squish(Dimensions.x4); + .paddingVertical(Dimensions.x4); } } diff --git a/example/pubspec.lock b/example/pubspec.lock index 9acae33d..7fe20582 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+19" + version: "0.1.1+20" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/grid_test.dart b/example/test/grid_test.dart deleted file mode 100644 index c766503e..00000000 --- a/example/test/grid_test.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:zeta_example/pages/grid_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; -import 'test_components.dart'; - -void main() { - testWidgets('Grid component default desktop', (tester) async { - await tester.pumpWidget( - TestWidget(widget: ZetaGrid(children: List.generate(20, (index) => GridItem(key: Key(index.toString()))))), - ); - - final item0 = tester.getCenter(find.byKey(const Key('0'))); - final item11 = tester.getCenter(find.byKey(const Key('11'))); - final item12 = tester.getCenter(find.byKey(const Key('12'))); - - // First 12 items don't wrap - all grid items on same row - expect(item0.dy, item11.dy); - - // Items wrap after 12th item - expect(item0.dy != item12.dy, true); - }); - - testWidgets('Grid component default mobile', (tester) async { - await tester.pumpWidget( - TestWidget( - widget: ZetaGrid(children: List.generate(20, (index) => GridItem(key: Key(index.toString())))), - screenSize: const Size(400, 600), - ), - ); - - final item0 = tester.getCenter(find.byKey(const Key('0'))); - final item1 = tester.getCenter(find.byKey(const Key('1'))); - final item2 = tester.getCenter(find.byKey(const Key('2'))); - - // First 2 items are on same row - expect(item0.dy, item1.dy); - - // Grid wraps at 2 columns - expect(item1.dy == item2.dy, false); - }); -} diff --git a/example/test/spacing_test.dart b/example/test/spacing_test.dart deleted file mode 100644 index cc6cf27a..00000000 --- a/example/test/spacing_test.dart +++ /dev/null @@ -1,188 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; -import 'test_components.dart'; - -void main() { - const Widget testChild = Text('Item'); - const Key control = Key('control'); - - testWidgets('Square', (tester) async { - await tester.pumpWidget( - TestWidget( - widget: Column( - children: [ - const SizedBox(key: Key('1'), child: ZetaSpacing(testChild, size: Dimensions.x1)), - const SizedBox( - key: Key('2'), - child: ZetaSpacing.square(testChild, size: Dimensions.x1), - ), - SizedBox(key: const Key('3'), child: testChild.square(Dimensions.x1)), - SizedBox(key: const Key('4'), child: Padding(padding: Dimensions.x1.square, child: testChild)), - const SizedBox( - key: control, - child: Padding(padding: EdgeInsets.all(4), child: testChild), - ), - ], - ), - ), - ); - - final item1 = tester.getSize(find.byKey(const Key('1'))); - final item2 = tester.getSize(find.byKey(const Key('2'))); - final item3 = tester.getSize(find.byKey(const Key('3'))); - final item4 = tester.getSize(find.byKey(const Key('4'))); - final controlItem = tester.getSize(find.byKey(control)); - - // Test all spacing methods return same size widget - expect(item1, item2); - expect(item2, item3); - expect(item3, item4); - - // Test spacing component against known correct control item - expect(item1, controlItem); - }); - testWidgets('Squish', (tester) async { - await tester.pumpWidget( - TestWidget( - widget: Column( - children: [ - const SizedBox(key: Key('1'), child: ZetaSpacing.squish(testChild, size: Dimensions.x1)), - SizedBox(key: const Key('2'), child: testChild.squish(Dimensions.x1)), - SizedBox(key: const Key('3'), child: Padding(padding: Dimensions.x1.squish, child: testChild)), - const SizedBox( - key: control, - child: Padding(padding: EdgeInsets.symmetric(vertical: 4), child: testChild), - ), - ], - ), - ), - ); - - final item1 = tester.getSize(find.byKey(const Key('1'))); - final item2 = tester.getSize(find.byKey(const Key('2'))); - final item3 = tester.getSize(find.byKey(const Key('3'))); - final controlItem = tester.getSize(find.byKey(control)); - - // Test all spacing methods return same size widget - expect(item1, item2); - expect(item2, item3); - - // Test spacing component against known correct control item - expect(item1, controlItem); - }); - - testWidgets('Stack', (tester) async { - await tester.pumpWidget( - TestWidget( - widget: Column( - children: [ - const SizedBox(key: Key('1'), child: ZetaSpacing.stack(testChild, size: Dimensions.x1)), - SizedBox(key: const Key('2'), child: testChild.stack(Dimensions.x1)), - SizedBox(key: const Key('3'), child: Padding(padding: Dimensions.x1.stack, child: testChild)), - const SizedBox(key: control, child: Padding(padding: EdgeInsets.only(bottom: 4), child: testChild)), - ], - ), - ), - ); - - final item1 = tester.getSize(find.byKey(const Key('1'))); - final item2 = tester.getSize(find.byKey(const Key('2'))); - final item3 = tester.getSize(find.byKey(const Key('3'))); - final controlItem = tester.getSize(find.byKey(control)); - - // Test all spacing methods return same size widget - expect(item1, item2); - expect(item2, item3); - - // Test spacing component against known correct control item - expect(item1, controlItem); - }); - testWidgets('Inline', (tester) async { - await tester.pumpWidget( - TestWidget( - widget: Column( - children: [ - const SizedBox(key: Key('1'), child: ZetaSpacing.inline(testChild, size: Dimensions.x1)), - SizedBox(key: const Key('2'), child: testChild.inline(Dimensions.x1)), - SizedBox(key: const Key('3'), child: Padding(padding: Dimensions.x1.inline, child: testChild)), - const SizedBox( - key: control, - child: Padding(padding: EdgeInsets.symmetric(horizontal: 4), child: testChild), - ), - ], - ), - ), - ); - - final item1 = tester.getSize(find.byKey(const Key('1'))); - final item2 = tester.getSize(find.byKey(const Key('2'))); - final item3 = tester.getSize(find.byKey(const Key('3'))); - final controlItem = tester.getSize(find.byKey(control)); - - // Test all spacing methods return same size widget - expect(item1, item2); - expect(item2, item3); - - // Test spacing component against known correct control item - expect(item1, controlItem); - }); - testWidgets('Inline Start', (tester) async { - await tester.pumpWidget( - TestWidget( - widget: Column( - children: [ - const SizedBox(key: Key('1'), child: ZetaSpacing.inlineStart(testChild, size: Dimensions.x1)), - SizedBox(key: const Key('2'), child: testChild.inlineStart(Dimensions.x1)), - SizedBox(key: const Key('3'), child: Padding(padding: Dimensions.x1.inlineStart, child: testChild)), - const SizedBox( - key: control, - child: Padding(padding: EdgeInsetsDirectional.only(start: 4), child: testChild), - ), - ], - ), - ), - ); - - final item1 = tester.getSize(find.byKey(const Key('1'))); - final item2 = tester.getSize(find.byKey(const Key('2'))); - final item3 = tester.getSize(find.byKey(const Key('3'))); - final controlItem = tester.getSize(find.byKey(control)); - - // Test all spacing methods return same size widget - expect(item1, item2); - expect(item2, item3); - - // Test spacing component against known correct control item - expect(item1, controlItem); - }); - testWidgets('Inline end', (tester) async { - await tester.pumpWidget( - TestWidget( - widget: Column( - children: [ - const SizedBox(key: Key('1'), child: ZetaSpacing.inlineEnd(testChild, size: Dimensions.x1)), - SizedBox(key: const Key('2'), child: testChild.inlineEnd(Dimensions.x1)), - SizedBox(key: const Key('3'), child: Padding(padding: Dimensions.x1.inlineEnd, child: testChild)), - const SizedBox( - key: control, - child: Padding(padding: EdgeInsetsDirectional.only(end: 4), child: testChild), - ), - ], - ), - ), - ); - - final item1 = tester.getSize(find.byKey(const Key('1'))); - final item2 = tester.getSize(find.byKey(const Key('2'))); - final item3 = tester.getSize(find.byKey(const Key('3'))); - final controlItem = tester.getSize(find.byKey(control)); - - // Test all spacing methods return same size widget - expect(item1, item2); - expect(item2, item3); - - // Test spacing component against known correct control item - expect(item1, controlItem); - }); -} diff --git a/example/widgetbook/components/color_widgetbook.dart b/example/widgetbook/components/color_widgetbook.dart index ccae7570..a59acb93 100644 --- a/example/widgetbook/components/color_widgetbook.dart +++ b/example/widgetbook/components/color_widgetbook.dart @@ -73,7 +73,7 @@ WidgetbookComponent colorWidgetBook() { MyRow(children: backdrop, title: 'Backdrop colors'), MyRow(children: alerts, title: 'Alert colors'), Row(children: [Text('Full color swatches', style: ZetaTextStyles.displayMedium)]) - .squish(Dimensions.x8), + .paddingVertical(Dimensions.x8), ...swatches.entries.map( (value) { return Row( diff --git a/example/widgetbook/components/grid_widgetbook.dart b/example/widgetbook/components/grid_widgetbook.dart deleted file mode 100644 index 72409360..00000000 --- a/example/widgetbook/components/grid_widgetbook.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart' hide DeviceType; -import 'package:zeta_example/pages/grid_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent gridWidgetBook() { - return WidgetbookComponent( - name: 'Grid', - useCases: [ - WidgetbookUseCase( - name: 'Basic Grid', - builder: (context) => SingleChildScrollView( - child: ZetaGrid( - col: context.knobs.double.slider(label: 'col', min: 2, max: 16, divisions: 7, initialValue: 12), - noGaps: context.knobs.boolean(label: 'No Gaps'), - children: List.generate(16, (index) => const GridItem()), - ), - ), - ), - WidgetbookUseCase( - name: 'Asymmetrical Grid', - builder: (context) => SingleChildScrollView( - child: ZetaGrid( - asymmetricWeight: context.knobs.double.slider(label: 'Asymmetric', min: 1, max: 11, divisions: 10).toInt(), - noGaps: context.knobs.boolean(label: 'No Gaps'), - children: List.generate(16, (index) => const GridItem()), - ), - ), - ), - WidgetbookUseCase( - name: 'Hybrid Grid', - builder: (context) => LayoutBuilder( - builder: (context, constraints) { - final double initialSize = constraints.maxWidth * 0.01; - final double maxSize = (constraints.maxWidth - (context.knobs.boolean(label: 'No Gaps') ? 0 : 40)) * 0.2; - - return ZetaGrid( - noGaps: context.knobs.boolean(label: 'No Gaps'), - col: 7, - hybrid: true, - children: [ - GridItem( - width: context.knobs.double - .slider(label: 'Fixed width 1', min: 1, max: maxSize, initialValue: initialSize), - label: 'Fixed 1', - ), - Flexible( - fit: FlexFit.tight, - flex: context.knobs.double.slider(label: 'Flex width 1', min: 0, max: 5, initialValue: 1).toInt(), - child: const GridItem(label: 'Flex 1'), - ), - GridItem( - width: context.knobs.double - .slider(label: 'Fixed width 2', min: 1, max: maxSize, initialValue: initialSize), - label: 'Fixed 2', - ), - Flexible( - fit: FlexFit.tight, - flex: context.knobs.double.slider(label: 'Flex width 2', min: 0, max: 5, initialValue: 1).toInt(), - child: const GridItem(label: 'Flex 2'), - ), - GridItem( - width: context.knobs.double - .slider(label: 'Fixed width 3', min: 1, max: maxSize, initialValue: initialSize), - label: 'Fixed 3', - ), - Flexible( - fit: FlexFit.tight, - flex: context.knobs.double.slider(label: 'Flex width 3', min: 0, max: 5, initialValue: 1).toInt(), - child: const GridItem(label: 'Flex 3'), - ), - GridItem( - width: context.knobs.double - .slider(label: 'Fixed width 4', min: 1, max: maxSize, initialValue: initialSize), - label: 'Fixed 4', - ), - ], - ); - }, - ), - ) - ], - ); -} diff --git a/example/widgetbook/components/spacing_widgetbook.dart b/example/widgetbook/components/spacing_widgetbook.dart deleted file mode 100644 index 95117c91..00000000 --- a/example/widgetbook/components/spacing_widgetbook.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart' hide DeviceType; -import 'package:zeta_example/pages/spacing_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -const List typeSelector = [ - ZetaSpacingType.square, - ZetaSpacingType.squish, - ZetaSpacingType.inline, - ZetaSpacingType.inlineStart, - ZetaSpacingType.inlineEnd, - ZetaSpacingType.stack, -]; -WidgetbookComponent spacingWidgetbook() { - final tShirtSizes = { - 'xxs': Dimensions.xxs, - 'xs': Dimensions.xs, - 's': Dimensions.s, - 'm': Dimensions.m, - 'l': Dimensions.l, - 'xl': Dimensions.xl, - 'xxl': Dimensions.xxl, - 'xxxl': Dimensions.xxxl, - }; - return WidgetbookComponent( - name: 'Spacing', - useCases: [ - WidgetbookUseCase( - name: 'Defined numbers', - builder: (context) => SingleChildScrollView( - child: Row( - children: [ - Expanded( - child: ColoredBox( - color: const Color(0xFFcce2fa), - child: ZetaSpacing( - const SpacingItem(), - size: context.knobs.list( - label: 'Size', - labelBuilder: (p0) => 'x${p0 ~/ 4}', - options: const [ - Dimensions.x0, - Dimensions.x1, - Dimensions.x2, - Dimensions.x3, - Dimensions.x3, - Dimensions.x4, - Dimensions.x5, - Dimensions.x6, - Dimensions.x7, - Dimensions.x8, - Dimensions.x9, - Dimensions.x10, - Dimensions.x12, - Dimensions.x16, - Dimensions.x20, - Dimensions.x24, - ], - ), - type: context.knobs.list(label: 'Spacing Type', options: typeSelector), - ), - ), - ), - ], - ), - ), - ), - WidgetbookUseCase( - name: 'T-Shirt Sizes', - builder: (context) => SingleChildScrollView( - child: Row( - children: [ - Expanded( - child: ColoredBox( - color: const Color(0xFFcce2fa), - child: ZetaSpacing( - const SpacingItem(), - size: context.knobs.list( - label: 'Size', - labelBuilder: (p0) => tShirtSizes.entries.firstWhere((element) => element.value == p0).key, - options: tShirtSizes.values.toList(), - ), - type: context.knobs.list(label: 'Spacing Type', options: typeSelector), - ), - ), - ), - ], - ), - ), - ), - WidgetbookUseCase( - name: 'Numbers', - builder: (context) => SingleChildScrollView( - child: Row( - children: [ - Expanded( - child: ColoredBox( - color: const Color(0xFFcce2fa), - child: ZetaSpacing( - const SpacingItem(), - size: (context.knobs.double.slider( - label: 'Size (rounding to nearest even int)', - min: 0, - max: 96, - initialValue: 0, - ) ~/ - 2) * - 2, - type: context.knobs.list(label: 'Spacing Type', options: typeSelector), - ), - ), - ), - ], - ), - ), - ), - ], - ); -} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 539859e7..3f29b8d6 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -9,14 +9,12 @@ import 'components/bottom_sheet_widgetbook.dart'; import 'components/button_widgetbook.dart'; import 'components/checkbox_widgetbook.dart'; import 'components/color_widgetbook.dart'; -import 'components/grid_widgetbook.dart'; import 'components/in_page_banner_widgetbook.dart'; import 'components/indicator_widgetbook.dart'; import 'components/chip_widgetbook.dart'; import 'components/menu_items_widgetbook.dart'; import 'components/password_input_widgetbook.dart'; import 'components/priority_pill_widgetbook.dart'; -import 'components/spacing_widgetbook.dart'; import 'components/status_label_widgetbook.dart'; import 'components/tag_widgetbook.dart'; import 'components/workcloud_indicator_widgetbook.dart'; @@ -35,8 +33,6 @@ class HotReload extends StatelessWidget { WidgetbookCategory( name: 'Components', children: [ - gridWidgetBook(), - spacingWidgetbook(), colorWidgetBook(), statusLabelWidgetBook(), tagWidgetBook(), diff --git a/lib/src/components/badges/indicator.dart b/lib/src/components/badges/indicator.dart index 61c4fc31..1ceeb78f 100644 --- a/lib/src/components/badges/indicator.dart +++ b/lib/src/components/badges/indicator.dart @@ -225,7 +225,9 @@ class _InnerContent extends StatelessWidget { child: Text( strVal.length > 1 ? '9+' : strVal, textAlign: strVal.length == 1 ? TextAlign.center : TextAlign.right, - style: size == ZetaIndicatorSize.large ? ZetaTextStyles.labelIndicator : ZetaTextStyles.labelTiny, + style: (size == ZetaIndicatorSize.large ? ZetaTextStyles.labelIndicator : ZetaTextStyles.labelTiny).apply( + color: Zeta.of(context).colors.white, + ), ), ); } diff --git a/lib/src/components/badges/workcloud_indicator.dart b/lib/src/components/badges/workcloud_indicator.dart index ba372d09..a5ceab54 100644 --- a/lib/src/components/badges/workcloud_indicator.dart +++ b/lib/src/components/badges/workcloud_indicator.dart @@ -140,7 +140,7 @@ class ZetaWorkcloudIndicator extends StatelessWidget { children: [ _buildPriorityPillIndex(size, colors, textStyle, theme), if (prioritySize != ZetaWidgetSize.small) ...[ - _buildPriorityPillLabel(size, textStyle, padding), + _buildPriorityPillLabel(textStyle, padding), ], ], ), @@ -172,12 +172,10 @@ class ZetaWorkcloudIndicator extends StatelessWidget { } Widget _buildPriorityPillLabel( - double size, TextStyle textStyle, EdgeInsets padding, ) { return Container( - height: size, constraints: const BoxConstraints(minWidth: 34), child: Padding( padding: padding, diff --git a/lib/src/components/banners/in_page_banner.dart b/lib/src/components/banners/in_page_banner.dart index 114adfa8..e96e2052 100644 --- a/lib/src/components/banners/in_page_banner.dart +++ b/lib/src/components/banners/in_page_banner.dart @@ -164,7 +164,7 @@ class ZetaInPageBanner extends StatelessWidget { child: Padding( padding: EdgeInsets.only(left: hasTitle ? Dimensions.x7 : Dimensions.x0), child: DefaultTextStyle( - style: ZetaTextStyles.bodyMedium, + style: ZetaTextStyles.bodyMedium.apply(color: theme.colors.textDefault), child: content, ), ), diff --git a/lib/src/legacy/grid.dart b/lib/src/legacy/grid.dart deleted file mode 100644 index ea0a8636..00000000 --- a/lib/src/legacy/grid.dart +++ /dev/null @@ -1,156 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -import '../theme/breakpoints.dart'; -import '../theme/tokens.dart' as tokens; - -import '../utils/extensions.dart'; - -extension _Spacing on DeviceType { - num maxCrossAxisCount(num col) { - switch (this) { - case DeviceType.mobilePortrait: - return tokens.Grid.mobilePortraitCount; - case DeviceType.mobileLandscape: - return tokens.Grid.mobileLandscapeCount; - case DeviceType.tablet: - return col == tokens.Grid.maxCols ? tokens.Grid.tabletCount : col; - case DeviceType.desktop: - case DeviceType.desktopL: - case DeviceType.desktopXL: - return col; - } - } - - double axisSpacing(double col) { - switch (this) { - case DeviceType.mobilePortrait: - case DeviceType.mobileLandscape: - return tokens.Dimensions.x2; - case DeviceType.tablet: - case DeviceType.desktop: - case DeviceType.desktopL: - case DeviceType.desktopXL: - return col == tokens.Grid.maxCols ? tokens.Dimensions.x3 : tokens.Dimensions.x4; - } - } -} - -/// Zeta Grid. -class ZetaGrid extends StatelessWidget { - /// Constructs a [ZetaGrid]. - const ZetaGrid({ - required this.children, - this.col = tokens.Grid.defaultCols, - this.noGaps = false, - this.asymmetricWeight, - this.hybrid = false, - super.key, - }) : assert( - asymmetricWeight == null || (asymmetricWeight > 0 && asymmetricWeight < tokens.Grid.defaultCols), - 'If defined, asymmetricWeight should be in the range 1-11', - ); - - /// Number of columns in grid. Should be an even number between 2 and 16, although values above 12 should be used sparingly. - /// - /// Defaults to 12. - final double col; - - /// Removes gutters (gaps) from between children. - /// - /// Defaults to false. - final bool noGaps; - - /// `Required` list of children to be placed into the grid. - final List children; - - /// If not null, creates a 2 column asymmetric grid, where the first item has this weight. - /// - /// Example: `asymmetricWeight: 1` will create a grid with 2 columns, where the first has a width of 1/12 and the second has a width of 11/12. - final int? asymmetricWeight; - - /// If the Grid should allow custom child widths. - /// - /// Custom sized widgets can be mixed with Flexible wrapped widgets. - /// - /// This is potentially dangerous as children could exceed screen width, causing overflow errors. - /// - /// Defaults to false. - final bool hybrid; - - /// Util to return the smaller of 2 values. - num returnSmaller(num in1, num in2) { - return in1 > in2 ? in2 : in1; - } - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - final DeviceType deviceType = constraints.deviceType; - final crossAxisCount = returnSmaller(deviceType.maxCrossAxisCount(col), col); - final divider = (children.length / crossAxisCount).ceil(); - final List rows = []; - final double gutterSize = noGaps ? tokens.Dimensions.x0 : deviceType.axisSpacing(col); - final Widget gutter = SizedBox(width: gutterSize, height: gutterSize); - final Widget widget; - List children2 = [...children]; - - if (hybrid) { - if (children.length < col) { - children2 = [...children, ...List.generate((col - children.length).toInt(), (index) => const SizedBox())]; - } else if (children.length > col) { - children2 = children.getRange(0, col.toInt()).toList(); - } else { - children2 = children; - } - widget = Row( - children: [ - Expanded(child: Row(children: children2.divide(gutter).toList())), - ], - ); - } else if (asymmetricWeight != null) { - widget = Row( - children: [ - Flexible(flex: asymmetricWeight ?? 1, fit: FlexFit.tight, child: children.first), - gutter, - Flexible( - flex: (tokens.Grid.defaultCols - (asymmetricWeight ?? 1)).toInt(), - fit: FlexFit.tight, - child: children[1], - ), - ], - ); - } else { - if (children2.length % col != 0) { - children2.addAll(List.generate((col - (children.length % col)).toInt(), (index) => const SizedBox())); - } - for (int i = 0; i < divider; i++) { - rows.add( - Row( - children: children2 - .sublist((i * crossAxisCount).toInt(), ((children2.length / divider) * (i + 1)).round()) - .map((e) => Expanded(child: e)) - .divide(gutter) - .toList(), - ), - ); - } - widget = Column(children: rows.divide(gutter).toList()); - } - - return Padding(padding: const EdgeInsets.all(tokens.Grid.gridMargin), child: widget); - }, - ); - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('hybrid', hybrid)) - ..add(DoubleProperty('col', col)) - ..add(DiagnosticsProperty('noGaps', noGaps)) - ..add(IntProperty('asymmetricWeight', asymmetricWeight)); - } -} diff --git a/lib/src/legacy/spacing.dart b/lib/src/legacy/spacing.dart deleted file mode 100644 index 04d27ba8..00000000 --- a/lib/src/legacy/spacing.dart +++ /dev/null @@ -1,191 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; - -import '../theme/tokens.dart'; - -/// Spacing types for [ZetaSpacing]. - -enum ZetaSpacingType { - /// {@template zeta-spacing-square} - /// Identical spacing on all four sides. - /// - /// It’s use is widespread, across many components at varying sizes. - /// {@endtemplate} - square, - - /// {@template zeta-spacing-squish} - /// Identical padding on top and bottom, nothing on sides. - /// - /// While less common than its squared counterpart, a squish occurred frequently in elements (like a button) and cell-like containers like a data table or list item. - /// {@endtemplate} - squish, - - /// {@template zeta-spacing-stack} - /// Padding on bottom only. - /// - /// With all due respect to horizontally scrolled UI, the overwhelming majority scroll vertically. And that means one thing, we stack things. We stack message on heading on data table. We stack modules in rails. We stack copy, pills & toolbars, all in a card, each in a grid. Heck, infinite scroll means infinite stack! We stack, stack, stack. - /// {@endtemplate} - stack, - - /// {@template zeta-spacing-inline-only} - /// Padding on start and end only. - /// {@endtemplate} - /// {@template zeta-spacing-inline} - /// We arrange objects inline, wrapping as they flow like text from the left or right. Such objects — pills, tags, breadcrumbs, and more — may stand alone or stack and mingle with other objects. - /// {@endtemplate} - inline, - - /// {@template zeta-spacing-inline-start} - /// Padding on start only. - /// - /// {@macro zeta-spacing-inline} - /// - /// {@endtemplate} - inlineStart, - - /// {@template zeta-spacing-inline-end} - /// Padding on end only. - /// {@endtemplate} - inlineEnd, -} - -/// Zeta Spacing widget. -class ZetaSpacing extends StatelessWidget { - /// Constructs [ZetaSpacing]. - const ZetaSpacing( - this.child, { - this.type = ZetaSpacingType.square, - this.size = Dimensions.x0, - super.key, - }) : assert( - size % _mod == 0 && size >= 0 && size <= Dimensions.x24, - 'Size should be a whole, even number, and be no larger than [x24]', - ); - - /// Constructs a [ZetaSpacing] widget with [ZetaSpacingType.square] insets. - /// - /// {@macro zeta-spacing-square} - const ZetaSpacing.square(this.child, {this.size = Dimensions.x0, super.key}) : type = ZetaSpacingType.square; - - /// Constructs a [ZetaSpacing] widget with [ZetaSpacingType.squish] insets. - /// - /// {@macro zeta-spacing-squish} - const ZetaSpacing.squish(this.child, {this.size = Dimensions.x0, super.key}) : type = ZetaSpacingType.squish; - - /// Constructs a [ZetaSpacing] widget with [ZetaSpacingType.stack] insets. - /// - /// {@macro zeta-spacing-stack} - const ZetaSpacing.stack(this.child, {this.size = Dimensions.x0, super.key}) : type = ZetaSpacingType.stack; - - /// Constructs a [ZetaSpacing] widget with [ZetaSpacingType.inline] insets. - /// - /// {@macro zeta-spacing-inline-only} - /// - /// {@macro zeta-spacing-inline} - const ZetaSpacing.inline(this.child, {this.size = Dimensions.x0, super.key}) : type = ZetaSpacingType.inline; - - /// Constructs a [ZetaSpacing] widget with [ZetaSpacingType.inlineStart] insets. - /// - /// {@macro zeta-spacing-inline-start} - /// - /// {@macro zeta-spacing-inline} - const ZetaSpacing.inlineStart(this.child, {this.size = Dimensions.x0, super.key}) - : type = ZetaSpacingType.inlineStart; - - /// Constructs a [ZetaSpacing] widget with [ZetaSpacingType.inlineEnd] insets. - /// - /// {@macro zeta-spacing-inline-end} - /// - /// {@macro zeta-spacing-inline} - const ZetaSpacing.inlineEnd(this.child, {this.size = Dimensions.x0, super.key}) : type = ZetaSpacingType.inlineEnd; - static const double _mod = 2; - - /// Child to be wrapped with spacing insets. - final Widget child; - - /// [ZetaSpacingType] insets applied to [child]. - /// - /// Defaults to [ZetaSpacingType.square]. - final ZetaSpacingType? type; - - /// Size of insets to be applied around [child]. - /// - /// Should be an even number, and be no larger than [Dimensions.x24]. - /// - /// Defaults to [Dimensions.x0]. - final double size; - - @override - Widget build(BuildContext context) { - switch (type ?? ZetaSpacingType.square) { - case ZetaSpacingType.square: - return child.square(size); - case ZetaSpacingType.squish: - return child.squish(size); - case ZetaSpacingType.stack: - return child.stack(size); - case ZetaSpacingType.inline: - return child.inline(size); - case ZetaSpacingType.inlineStart: - return child.inlineStart(size); - case ZetaSpacingType.inlineEnd: - return child.inlineEnd(size); - } - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(EnumProperty('type', type)) - ..add(DoubleProperty('size', size)); - } -} - -/// Extension to get Spacing type as [EdgeInsets] from a double. -extension SpacingSize on double { - /// {@macro zeta-spacing-square} - EdgeInsets get square => EdgeInsets.all(this); - - /// {@macro zeta-spacing-squish} - EdgeInsets get squish => EdgeInsets.symmetric(vertical: this); - - /// {@macro zeta-spacing-stack} - EdgeInsets get stack => EdgeInsets.only(bottom: this); - - /// {@macro zeta-spacing-inline} - EdgeInsetsDirectional get inline => EdgeInsetsDirectional.only(start: this, end: this); - - /// {@macro zeta-spacing-inline-start} - EdgeInsetsDirectional get inlineStart => EdgeInsetsDirectional.only(start: this); - - /// {@macro zeta-spacing-inline-end} - EdgeInsetsDirectional get inlineEnd => EdgeInsetsDirectional.only(end: this); -} - -/// Extension to add spacing to any [Widget]. -extension SpacingWidget on Widget { - /// {@macro zeta-spacing-square} - Widget square(double space) => Padding(padding: space.square, child: this); - - /// {@macro zeta-spacing-squish} - Widget squish(double space) => Padding(padding: space.squish, child: this); - - /// {@macro zeta-spacing-stack} - Widget stack(double space) => Padding(padding: space.stack, child: this); - - /// {@macro zeta-spacing-inline-only} - /// - /// {@macro zeta-spacing-inline} - Widget inline(double space) => Padding(padding: space.inline, child: this); - - /// {@macro zeta-spacing-inline-end} - /// - /// {@macro zeta-spacing-inline} - Widget inlineStart(double space) => Padding(padding: space.inlineStart, child: this); - - /// {@macro zeta-spacing-inline-end} - /// - /// {@macro zeta-spacing-inline} - Widget inlineEnd(double space) => Padding(padding: space.inlineEnd, child: this); -} diff --git a/lib/src/theme/tokens.dart b/lib/src/theme/tokens.dart index 196a91c9..0f46e869 100644 --- a/lib/src/theme/tokens.dart +++ b/lib/src/theme/tokens.dart @@ -1,8 +1,8 @@ -import '../../../zeta_flutter.dart'; - -/// Tokens that are used for [ZetaSpacing]. +/// Tokens that are used for Spacing. /// /// Values are doubles, and can be used for padding, margins and other spacings. +/// +// TODO(thelukewalton): Refactor to match latest designs. class Dimensions { /// Base multiplier used to calculate spacing values. static const double spacingBaseMultiplier = 4; @@ -91,24 +91,3 @@ class Dimensions { /// 96dp space. static const double xxxl = spacingBaseMultiplier * 24; } - -/// Tokens that are used for [ZetaGrid]. -class Grid { - /// Maximum number of cols that can be displayed. - static const double maxCols = 16; - - /// Default number of cols. - static const double defaultCols = 12; - - /// Default margin for grid component. - static const double gridMargin = Dimensions.x6; - - /// Number of columns to show on a portrait mobile, as defined in [DeviceType.mobilePortrait]. - static const mobilePortraitCount = 2; - - /// Number of columns to show on a landscape mobile, as defined in [DeviceType.mobileLandscape]. - static const mobileLandscapeCount = 4; - - /// Number of columns to show on a tablet, as defined in [DeviceType.tablet]. - static const tabletCount = 8; -} diff --git a/lib/src/utils/extensions.dart b/lib/src/utils/extensions.dart index 59eb32cc..f78f72eb 100644 --- a/lib/src/utils/extensions.dart +++ b/lib/src/utils/extensions.dart @@ -16,3 +16,33 @@ extension ListDivider on Iterable { } } } + +/// Extension to add spacing to any [Widget]. +extension SpacingWidget on Widget { + /// Equal padding on all sides. + Widget paddingAll(double space) => Padding(padding: EdgeInsets.all(space), child: this); + + /// Padding on start edge only. Is affected by whether the device is LTR or RTL: + /// + /// LTR: Left edge + /// RTL: Right edge + Widget paddingStart(double space) => Padding(padding: EdgeInsetsDirectional.only(start: space), child: this); + + /// Padding on start edge only. Is affected by whether the device is LTR or RTL: + /// + /// LTR: Right edge + /// RTL: Left edge + Widget paddingEnd(double space) => Padding(padding: EdgeInsetsDirectional.only(end: space), child: this); + + /// Padding on bottom only. + Widget paddingBottom(double space) => Padding(padding: EdgeInsets.only(bottom: space), child: this); + + /// Padding on top only. + Widget paddingTop(double space) => Padding(padding: EdgeInsets.only(top: space), child: this); + + /// Equal padding on top and bottom. + Widget paddingVertical(double space) => Padding(padding: EdgeInsets.symmetric(vertical: space), child: this); + + /// Equal padding on start and end. + Widget paddingHorizontal(double space) => Padding(padding: EdgeInsets.symmetric(horizontal: space), child: this); +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index 9fc701d1..bccd6491 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -19,8 +19,6 @@ export 'src/components/buttons/fab.dart'; export 'src/components/checkbox/checkbox.dart'; export 'src/components/chip/chip.dart'; export 'src/components/password/password_input.dart'; -export 'src/legacy/grid.dart'; -export 'src/legacy/spacing.dart'; export 'src/theme/color_extensions.dart'; export 'src/theme/color_scheme.dart'; export 'src/theme/color_swatch.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 46b7fb8c..678eecd8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+20 +version: 0.1.1+21 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. From ed1210d6cbc173aef8b1adf0d20ee91d3e87f2c3 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Fri, 19 Jan 2024 11:29:10 +0000 Subject: [PATCH 31/41] chore: Update Widgetbook to correct functionality (#52) https://jira.zebra.com/browse/UX-912 --------- Co-authored-by: github-actions --- CHANGELOG.md | 22 ++- example/pubspec.lock | 2 +- example/test/test_components.dart | 5 +- .../components/accordion_widgetbook.dart | 48 +++-- .../components/avatar_widgetbook.dart | 78 ++++---- .../components/badge_widgetbook.dart | 61 ------ .../components/badges_widgetbook.dart | 173 ++++++++++++++++++ .../components/banner_widgetbook.dart | 83 +++++++++ .../components/bottom_sheet_widgetbook.dart | 58 +++++- .../components/button_widgetbook.dart | 141 +++++++++++++- .../components/checkbox_widgetbook.dart | 43 ++--- .../components/chip_widgetbook.dart | 85 +++++++-- .../components/color_widgetbook.dart | 130 ------------- .../components/in_page_banner_widgetbook.dart | 124 ------------- .../components/indicator_widgetbook.dart | 25 --- .../components/menu_items_widgetbook.dart | 25 --- .../components/password_input_widgetbook.dart | 104 +++++++---- .../components/priority_pill_widgetbook.dart | 34 ---- .../components/status_label_widgetbook.dart | 30 --- .../widgetbook/components/tag_widgetbook.dart | 20 -- .../workcloud_indicator_widgetbook.dart | 67 ------- .../widgetbook/theme/color_widgetbook.dart | 144 +++++++++++++++ example/widgetbook/widgetbook.dart | 27 +-- lib/src/theme/tokens.dart | 2 +- pubspec.yaml | 2 +- 25 files changed, 834 insertions(+), 699 deletions(-) delete mode 100644 example/widgetbook/components/badge_widgetbook.dart create mode 100644 example/widgetbook/components/badges_widgetbook.dart create mode 100644 example/widgetbook/components/banner_widgetbook.dart delete mode 100644 example/widgetbook/components/color_widgetbook.dart delete mode 100644 example/widgetbook/components/in_page_banner_widgetbook.dart delete mode 100644 example/widgetbook/components/indicator_widgetbook.dart delete mode 100644 example/widgetbook/components/menu_items_widgetbook.dart delete mode 100644 example/widgetbook/components/priority_pill_widgetbook.dart delete mode 100644 example/widgetbook/components/status_label_widgetbook.dart delete mode 100644 example/widgetbook/components/tag_widgetbook.dart delete mode 100644 example/widgetbook/components/workcloud_indicator_widgetbook.dart create mode 100644 example/widgetbook/theme/color_widgetbook.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 74a3d00c..db163553 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## [0.1.1+22] - 2024-01-19 +### :boom: BREAKING CHANGES +- due to [`7b543ac`](https://github.com/zebratechnologies/zeta-flutter/commit/7b543ac7b92dc53a866af4de313c36b5728e912e) - Remove legacy code *(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))*: + + Removed ZetaGrid and ZetaSpacing components, renamed widget padding extensions + https://jira.zebra.com/browse/UX-910 + Remove ZetaGrid, ZetaSpacing and ZetaText widgets as these are no longer + part of the library. Functionality is retained in some cases (text + styles, padding extensions) but widgets themselves are removed. + --------- + + +### :sparkles: New Features +- [`7b543ac`](https://github.com/zebratechnologies/zeta-flutter/commit/7b543ac7b92dc53a866af4de313c36b5728e912e) - Remove legacy code *(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))* + +### :wrench: Chores +- [`ccbdeb9`](https://github.com/zebratechnologies/zeta-flutter/commit/ccbdeb93b6995eb3a3ff66562d957bc7e2470432) - Update Widgetbook to correct functionality *(PR [#52](https://github.com/zebratechnologies/zeta-flutter/pull/52) by [@thelukewalton](https://github.com/thelukewalton))* + + ## [0.1.1+21] - 2024-01-18 ### :sparkles: New Features - [`6ae1269`](https://github.com/zebratechnologies/zeta-flutter/commit/6ae1269422180bbf2ecbfd05814969bfcbb725f1) - Update text styles to match latest designs *(PR [#50](https://github.com/zebratechnologies/zeta-flutter/pull/50) by [@thelukewalton](https://github.com/thelukewalton))* @@ -1731,4 +1750,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+18]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+17...0.1.1+18 [0.1.1+19]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+18...0.1.1+19 [0.1.1+20]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+19...0.1.1+20 -[0.1.1+21]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+20...0.1.1+21 \ No newline at end of file +[0.1.1+21]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+20...0.1.1+21 +[0.1.1+22]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+21...0.1.1+22 \ No newline at end of file diff --git a/example/pubspec.lock b/example/pubspec.lock index 7fe20582..a60f4020 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+20" + version: "0.1.1+21" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/test_components.dart b/example/test/test_components.dart index 29ac4a03..60197103 100644 --- a/example/test/test_components.dart +++ b/example/test/test_components.dart @@ -4,18 +4,21 @@ import 'package:zeta_flutter/zeta_flutter.dart'; class TestWidget extends StatelessWidget { final Size? screenSize; final Widget widget; + final ThemeMode? themeMode; - const TestWidget({required this.widget, this.screenSize, super.key}); + const TestWidget({required this.widget, this.screenSize, super.key, this.themeMode}); @override 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(), diff --git a/example/widgetbook/components/accordion_widgetbook.dart b/example/widgetbook/components/accordion_widgetbook.dart index 46a7477c..80719c1c 100644 --- a/example/widgetbook/components/accordion_widgetbook.dart +++ b/example/widgetbook/components/accordion_widgetbook.dart @@ -1,30 +1,40 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/accordion_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; WidgetbookComponent accordionWidgetBook() { return WidgetbookComponent( + isInitiallyExpanded: false, name: 'Accordion', useCases: [ WidgetbookUseCase( - name: 'Default', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: AccordionExample.accordionDefaultExample, - ), - ), - WidgetbookUseCase( - name: 'Contained', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: AccordionExample.accordionContainedExample, - ), - ), - WidgetbookUseCase( - name: 'Sharp', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: AccordionExample.accordionSharpExample, + name: 'Accordian', + builder: (context) => TestWidget( + themeMode: ThemeMode.dark, + widget: Padding( + padding: const EdgeInsets.all(20), + child: ZetaAccordion( + children: [ + ZetaAccordionSection( + title: Text(context.knobs.string(label: 'Accordion Title', initialValue: 'Title')), + disabled: context.knobs.boolean(label: 'Disabled', initialValue: false), + contained: context.knobs.boolean(label: 'Contained', initialValue: false), + isOpen: context.knobs.boolean(label: 'Open', initialValue: false), + rounded: context.knobs.boolean(label: 'Rounded', initialValue: false), + body: Column( + children: [ + ListTile(title: Text('Item One')), + ListTile(title: Text('Item two')), + ListTile(title: Text('Item three')), + ListTile(title: Text('Item four')), + ], + ), + ), + ], + ), + ), ), ), ], diff --git a/example/widgetbook/components/avatar_widgetbook.dart b/example/widgetbook/components/avatar_widgetbook.dart index f6535d15..faddc32b 100644 --- a/example/widgetbook/components/avatar_widgetbook.dart +++ b/example/widgetbook/components/avatar_widgetbook.dart @@ -1,52 +1,48 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/avatar_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; WidgetbookComponent avatarWidgetBook() { return WidgetbookComponent( + isInitiallyExpanded: false, name: 'Avatar', useCases: [ WidgetbookUseCase( - name: 'Photo', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: AvatarExample.avatarImageExample, - ), - ), - WidgetbookUseCase( - name: 'Initials', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: AvatarExample.avatarInitialsExample, - ), - ), - WidgetbookUseCase( - name: 'Photo with badge', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: AvatarExample.avatarImageWithBadgeExample, - ), - ), - WidgetbookUseCase( - name: 'Initials with badge', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: AvatarExample.avatarInitialsWithBadgeExample, - ), - ), - WidgetbookUseCase( - name: 'Photo with special status', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: AvatarExample.avatarImageWithSpecialStatusExample, - ), - ), - WidgetbookUseCase( - name: 'Initials with special status', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: AvatarExample.avatarInitialsWithSpecialStatusExample, - ), + name: 'Avatar', + builder: (context) { + return TestWidget( + themeMode: ThemeMode.dark, + widget: Column( + children: [ + Padding( + padding: const EdgeInsets.all(20), + child: ZetaAvatar( + type: context.knobs.list(label: 'Avatar type', options: ZetaAvatarType.values), + imageUrl: context.knobs.string( + label: 'Image URL', + initialValue: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + initials: context.knobs.string(label: 'Initials', initialValue: 'AZ'), + showStatus: context.knobs.boolean(label: 'Show Status'), + size: context.knobs.list(label: 'Size', options: ZetaAvatarSize.values), + badge: () { + final x = context.knobs.intOrNull.slider(label: 'Notifications', initialValue: null, max: 10); + if (x == null) return null; + return ZetaIndicator.notification(value: x); + }(), + specialStatus: + context.knobs.boolean(label: 'Status Icon', initialValue: false) ? ZetaIndicator.icon() : null, + backgroundColor: context.knobs.colorOrNull(label: 'Background color'), + statusPrimaryColor: context.knobs.colorOrNull(label: 'Status primary color'), + statusSecondaryColor: context.knobs.colorOrNull(label: 'Status secondary color'), + ), + ), + ], + ), + ); + }, ), ], ); diff --git a/example/widgetbook/components/badge_widgetbook.dart b/example/widgetbook/components/badge_widgetbook.dart deleted file mode 100644 index 558f175e..00000000 --- a/example/widgetbook/components/badge_widgetbook.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent badgeWidgetBook() { - return WidgetbookComponent( - name: 'Badge', - useCases: [ - WidgetbookUseCase( - name: 'Badge Rounded', - builder: (context) => SingleChildScrollView( - child: Column( - children: [ - _badgeExampleRow(WidgetSeverity.info), - _badgeExampleRow(WidgetSeverity.positive), - _badgeExampleRow(WidgetSeverity.warning), - _badgeExampleRow(WidgetSeverity.negative), - _badgeExampleRow(WidgetSeverity.neutral), - _badgeExampleRow(WidgetSeverity.custom, customColor: Colors.blue), - ], - ), - ), - ), - WidgetbookUseCase( - name: 'Badge Sharp', - builder: (context) => SingleChildScrollView( - child: Column( - children: [ - _badgeExampleRow(WidgetSeverity.info, isRounded: false), - _badgeExampleRow(WidgetSeverity.positive, isRounded: false), - _badgeExampleRow(WidgetSeverity.warning, isRounded: false), - _badgeExampleRow(WidgetSeverity.negative, isRounded: false), - _badgeExampleRow(WidgetSeverity.neutral, isRounded: false), - _badgeExampleRow( - WidgetSeverity.custom, - customColor: Colors.blue, - isRounded: false, - ), - ], - ), - ), - ), - ], - ); -} - -Widget _badgeExampleRow(WidgetSeverity type, {bool isRounded = true, Color? customColor}) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: EdgeInsets.symmetric(vertical: 10), - child: ZetaBadge( - label: 'Label', - severity: type, - customColor: customColor, - borderType: isRounded ? BorderType.rounded : BorderType.sharp, - )), - ]); -} diff --git a/example/widgetbook/components/badges_widgetbook.dart b/example/widgetbook/components/badges_widgetbook.dart new file mode 100644 index 00000000..134980ca --- /dev/null +++ b/example/widgetbook/components/badges_widgetbook.dart @@ -0,0 +1,173 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; + +WidgetbookComponent badgeWidgetBook() { + return WidgetbookComponent( + isInitiallyExpanded: false, + name: 'Badges', + useCases: [ + WidgetbookUseCase( + name: 'Status Label', + builder: (context) { + return TestWidget( + themeMode: ThemeMode.dark, + widget: Column( + children: [ + Padding( + padding: EdgeInsets.all(20), + child: ZetaStatusLabel( + label: context.knobs.string(label: 'Label', initialValue: 'Label'), + borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + severity: context.knobs.list(label: 'Status', options: WidgetSeverity.values), + customIcon: context.knobs.list( + label: 'Icon', + options: [ + ZetaIcons.star_half_round, + ZetaIcons.add_alert_round, + ZetaIcons.add_box_round, + ZetaIcons.barcode_round, + ], + labelBuilder: (value) { + if (value == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if (value == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if (value == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if (value == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + ), + isDefaultIcon: context.knobs.boolean(label: 'Use default Icon'), + ), + ), + ], + ), + ); + }, + ), + WidgetbookUseCase( + name: 'Priority Pill', + builder: (context) => TestWidget( + themeMode: ThemeMode.dark, + widget: Column( + children: [ + Padding( + padding: EdgeInsets.all(20), + child: ZetaPriorityPill( + index: context.knobs.int.slider(label: 'Index'), + priority: context.knobs.string(label: 'Priority', initialValue: 'Priority'), + borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + ), + ), + ], + ), + ), + ), + WidgetbookUseCase( + name: 'Badge', + builder: (context) => TestWidget( + themeMode: ThemeMode.dark, + widget: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.all(20), + child: ZetaBadge( + label: context.knobs.string(label: 'Label', initialValue: 'Label'), + borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + severity: context.knobs.list(label: 'Status', options: WidgetSeverity.values), + ), + ), + ], + ), + ), + ), + WidgetbookUseCase( + name: 'Indicators', + builder: (context) => TestWidget( + themeMode: ThemeMode.dark, + widget: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.all(20), + child: ZetaIndicator( + type: context.knobs.list(label: 'Type', options: ZetaIndicatorType.values), + backgroundColor: context.knobs.colorOrNull(label: 'Background Color'), + borderColor: context.knobs.colorOrNull(label: 'Border Color'), + foregroundColor: context.knobs.colorOrNull(label: 'Foreground Color'), + icon: context.knobs.list( + label: 'Icon', + options: [ + Icon(ZetaIcons.star_half_round), + Icon(ZetaIcons.add_alert_round), + Icon(ZetaIcons.add_box_round), + Icon(ZetaIcons.barcode_round), + ], + labelBuilder: (value) { + if (value?.icon == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if (value?.icon == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if (value?.icon == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if (value?.icon == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + ), + inverseBorder: context.knobs.boolean(label: 'Inverse Border'), + rounded: context.knobs.boolean(label: 'Rounded'), + size: context.knobs.list(label: 'Size', options: ZetaIndicatorSize.values), + value: context.knobs.int.slider(label: 'Value'), + ), + ), + ], + ), + ), + ), + WidgetbookUseCase( + name: 'Tags', + builder: (context) => TestWidget( + themeMode: ThemeMode.dark, + widget: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.all(20), + child: ZetaTag( + label: context.knobs.string(label: 'Label', initialValue: 'Tag'), + borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + direction: context.knobs.list(label: 'Direction', options: ZetaTagDirection.values), + ), + ) + ], + ), + ), + ), + WidgetbookUseCase( + name: 'Workcloud Indicators', + builder: (context) => TestWidget( + themeMode: ThemeMode.dark, + widget: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.all(20), + child: ZetaWorkcloudIndicator( + index: context.knobs.string(label: 'Index', initialValue: '1'), + isStatusBadge: context.knobs.boolean(label: 'Status Badge', initialValue: false), + label: context.knobs.string(label: 'Label', initialValue: 'Label'), + prioritySize: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), + priorityType: context.knobs.list(label: 'Type', options: ZetaWorkcloudIndicatorType.values), + ), + ) + ], + ), + ], + ), + ), + ), + ], + ); +} diff --git a/example/widgetbook/components/banner_widgetbook.dart b/example/widgetbook/components/banner_widgetbook.dart new file mode 100644 index 00000000..7dbfbd5d --- /dev/null +++ b/example/widgetbook/components/banner_widgetbook.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; + +WidgetbookComponent BannerWidgetBook() { + return WidgetbookComponent( + isInitiallyExpanded: false, + name: 'Banners', + useCases: [ + WidgetbookUseCase( + name: 'System Banner', + builder: (context) => TestWidget( + widget: Padding( + padding: EdgeInsets.all(20), + child: Column( + children: [ + ZetaSystemBanner( + title: Text(context.knobs.string(label: 'Title', initialValue: 'Banner Title')), + type: context.knobs.list(label: 'Type', options: ZetaSystemBannerType.values), + titleIcon: context.knobs.boolean(label: 'Leading Icon') ? Icon(ZetaIcons.info_round) : null, + centerTitle: context.knobs.boolean(label: 'Center title'), + actions: context.knobs.boolean(label: 'Trailing Icon') + ? [IconButton(icon: Icon(ZetaIcons.chevron_right_round), onPressed: () {})] + : null, + ), + ], + ), + ), + ), + ), + WidgetbookUseCase( + name: 'In Page Banner', + builder: (context) => TestWidget( + themeMode: ThemeMode.dark, + widget: Padding( + padding: EdgeInsets.all(20), + child: Column( + children: [ + ZetaInPageBanner( + content: Text( + context.knobs.string( + label: 'content', + initialValue: + 'Lorem ipsum dolor sit amet, conse ctetur cididunt ut labore et do lore magna aliqua.', + ), + ), + severity: context.knobs.list(label: 'Severity', options: WidgetSeverity.values), + showIconClose: context.knobs.boolean(label: 'Show Close icon'), + title: context.knobs.string(label: 'Title', initialValue: 'Title'), + borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + firstButton: context.knobs.boolean(label: 'First Button') + ? ZetaPageBannerButton(onPressed: () {}, label: 'Button') + : null, + secondButton: context.knobs.boolean(label: 'Second Button') + ? ZetaPageBannerButton(onPressed: () {}, label: 'Button') + : null, + customIcon: context.knobs.list( + label: 'Icon', + options: [ + ZetaIcons.star_half_round, + ZetaIcons.add_alert_round, + ZetaIcons.add_box_round, + ZetaIcons.barcode_round, + ], + labelBuilder: (value) { + if (value == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if (value == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if (value == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if (value == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + ), + ) + ], + ), + ), + ), + ), + ], + ); +} diff --git a/example/widgetbook/components/bottom_sheet_widgetbook.dart b/example/widgetbook/components/bottom_sheet_widgetbook.dart index 93c11a8b..00d42267 100644 --- a/example/widgetbook/components/bottom_sheet_widgetbook.dart +++ b/example/widgetbook/components/bottom_sheet_widgetbook.dart @@ -1,25 +1,63 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/bottom_sheet.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; WidgetbookComponent bottomSheetWidgetBook() { return WidgetbookComponent( + isInitiallyExpanded: false, name: 'Bottom Sheet', useCases: [ WidgetbookUseCase( - name: 'Centered title', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: BottomSheetExample.bottomSheet(context), + name: 'Content', + builder: (context) => TestWidget( + themeMode: ThemeMode.dark, + widget: Padding( + padding: const EdgeInsets.all(20), + child: _bottomSheet(context), + ), ), ), WidgetbookUseCase( - name: 'Title aligned left', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: BottomSheetExample.bottomSheet(context, Alignment.centerLeft), - ), + name: 'Live', + builder: (context) { + final sheet = _bottomSheet(context); + return TestWidget( + widget: Padding( + padding: const EdgeInsets.all(20), + child: ElevatedButton( + child: Text('Open'), + onPressed: () { + showModalBottomSheet(context: context, builder: (_) => sheet); + }, + ), + ), + ); + }, ), ], ); } + +ZetaBottomSheet _bottomSheet(BuildContext context) { + return ZetaBottomSheet( + titleAlignment: context.knobs.boolean(label: 'Center align header') ? Alignment.center : Alignment.centerLeft, + title: context.knobs.string(label: 'Title', initialValue: 'Title'), + body: Wrap( + spacing: 12, + runSpacing: 12, + children: List.generate( + 6, + (index) => ZetaMenuItem( + type: context.knobs.boolean(label: 'Grid') ? ZetaMenuItemType.vertical : ZetaMenuItemType.horizontal, + leadingIcon: context.knobs.boolean(label: 'Leading Icon') ? Icon(ZetaIcons.star_round) : null, + trailingIcon: context.knobs.boolean(label: 'Trailing Icon') ? Icon(ZetaIcons.chevron_right_round) : null, + label: Text('Menu Item'), + onTap: () {}, + disabled: context.knobs.boolean(label: 'Disabled'), + ), + ), + ), + ); +} diff --git a/example/widgetbook/components/button_widgetbook.dart b/example/widgetbook/components/button_widgetbook.dart index 75df80a2..4166d90d 100644 --- a/example/widgetbook/components/button_widgetbook.dart +++ b/example/widgetbook/components/button_widgetbook.dart @@ -3,24 +3,145 @@ import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_example/pages/button_example.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; +import '../../test/test_components.dart'; + WidgetbookComponent buttonWidgetBook() { return WidgetbookComponent( name: 'Button', + isInitiallyExpanded: false, useCases: [ WidgetbookUseCase( - name: 'Button Rounded', - builder: (context) => SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: roundedButtonsExample(BuildExampleButtonColors(theme: Zeta.of(context))), - ), + name: 'Button', + builder: (context) { + final buttonColors = BuildExampleButtonColors(theme: Zeta.of(context)); + List all = [ + buttonColors.primaryColors, + buttonColors.primaryVariantColors, + buttonColors.negativeColors, + buttonColors.outlined, + buttonColors.outlinedSubtle, + buttonColors.textColors, + buttonColors.textInverseColor, + ]; + + return TestWidget( + widget: Padding( + padding: EdgeInsets.all(20), + child: ZetaButton( + label: context.knobs.string(label: 'Text', initialValue: 'Button'), + colors: context.knobs.list( + label: 'Colors', + options: all, + labelBuilder: (value) { + if (value.backgroundColor == buttonColors.primaryColors.backgroundColor) return 'Primary'; + if (value.backgroundColor == buttonColors.primaryVariantColors.backgroundColor) + return 'Primary Variant'; + if (value.backgroundColor == buttonColors.negativeColors.backgroundColor) return 'Negative'; + if (value.foregroundColor == buttonColors.textColors.foregroundColor) return 'Text'; + if (value.actionColor == buttonColors.outlined.actionColor) return 'Outlined'; + if (value.actionColor == buttonColors.outlinedSubtle.actionColor) return 'Outline Subtle'; + if (value.actionColor == buttonColors.textInverseColor.actionColor) return 'Text Inverse'; + return ''; + }, + ), + onPressed: context.knobs.boolean(label: 'Disabled') ? null : () {}, + borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + icon: context.knobs.list( + label: 'Icon', + options: [ + ZetaIcons.star_half_round, + ZetaIcons.add_alert_round, + ZetaIcons.add_box_round, + ZetaIcons.barcode_round, + ], + labelBuilder: (value) { + if (value == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if (value == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if (value == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if (value == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + ), + iconOnRight: context.knobs.boolean(label: 'Icon on right'), + size: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), + type: context.knobs.list(label: 'Type', options: ZetaButtonType.values), + ), + ), + ); + }, ), WidgetbookUseCase( - name: 'Button Sharp', - builder: (context) => SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: sharpButtonsExample(BuildExampleButtonColors(theme: Zeta.of(context))), + name: 'Floating Action Button', + builder: (context) => TestWidget( + widget: Padding(padding: EdgeInsets.all(20), child: FabWidget(context)), ), - ), + ) ], ); } + +class FabWidget extends StatefulWidget { + const FabWidget(this.c); + final BuildContext c; + + @override + State createState() => _FabWidgetState(); +} + +class _FabWidgetState extends State { + late ScrollController _scrollController; + + @override + void initState() { + super.initState(); + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext _) { + return SizedBox( + height: MediaQuery.of(context).size.height * 0.9, + child: Scaffold( + body: ListView.builder( + itemCount: MediaQuery.of(context).size.height.toInt(), + controller: _scrollController, + itemBuilder: (context, index) { + return Text("$index"); + }, + ), + floatingActionButton: ZetaFAB( + scrollController: _scrollController, + buttonLabel: widget.c.knobs.string(label: 'Label', initialValue: 'Floating Action Button'), + onPressed: widget.c.knobs.boolean(label: 'Disabled') ? null : () {}, + buttonIcon: widget.c.knobs.list( + label: 'Icon', + options: [ + ZetaIcons.star_half_round, + ZetaIcons.add_alert_round, + ZetaIcons.add_box_round, + ZetaIcons.barcode_round, + ], + labelBuilder: (value) { + if (value == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if (value == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if (value == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if (value == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + ), + buttonShape: widget.c.knobs.list(label: 'Shape', options: ZetaFabShape.values), + buttonSize: widget.c.knobs.list(label: 'Shape', options: ZetaFabSize.values), + buttonType: widget.c.knobs.list(label: 'Shape', options: ZetaFabType.values), + customAnimationDuration: + widget.c.knobs.duration(label: 'Animation Duration', initialValue: Duration(milliseconds: 100)), + ), + ), + ); + } +} diff --git a/example/widgetbook/components/checkbox_widgetbook.dart b/example/widgetbook/components/checkbox_widgetbook.dart index 6909ee4e..4df00343 100644 --- a/example/widgetbook/components/checkbox_widgetbook.dart +++ b/example/widgetbook/components/checkbox_widgetbook.dart @@ -1,35 +1,30 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/checkbox_example.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 (sharp)', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.only(top: 10), - child: getCheckBoxRow(isEnabled: true), - ), - ), - ), - WidgetbookUseCase( - name: 'Checkbox (rounded)', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.only(top: 10), - child: getCheckBoxRow(isEnabled: true, isSharp: false), - ), - ), - ), - WidgetbookUseCase( - name: 'Checkbox disabled (rounded)', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.only(top: 10), - child: getCheckBoxRow(isEnabled: false, isSharp: false), + name: 'Checkbox', + builder: (context) => TestWidget( + widget: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 10), + child: ZetaCheckbox( + value: context.knobs.booleanOrNull(label: 'Checked'), + onChanged: (_) {}, + borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + isEnabled: context.knobs.boolean(label: 'Enabled', initialValue: true), + 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 28e79469..3ec6a6d7 100644 --- a/example/widgetbook/components/chip_widgetbook.dart +++ b/example/widgetbook/components/chip_widgetbook.dart @@ -1,44 +1,91 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/chip_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; WidgetbookComponent chipWidgetBook() { return WidgetbookComponent( + isInitiallyExpanded: false, name: 'Chip', useCases: [ WidgetbookUseCase( name: 'Input Chip', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: ChipExample.inputChipExample, + builder: (context) => TestWidget( + widget: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + ZetaChip.input( + label: context.knobs.string(label: 'Label', initialValue: 'Label'), + leading: context.knobs.boolean(label: 'Avatar') + ? ZetaAvatar.initials(initials: 'AZ', size: ZetaAvatarSize.xs) + : null, + rounded: context.knobs.boolean(label: 'Rounded'), + onDelete: context.knobs.boolean(label: 'Delete') ? () {} : null, + ), + ], + ), ), ), ), WidgetbookUseCase( - name: 'Assist Chip', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: ChipExample.assistChipExample, + name: 'Filter Chip', + builder: (context) => TestWidget( + widget: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + ZetaFilterChip( + label: context.knobs.string(label: 'Label', initialValue: 'Label'), + rounded: context.knobs.boolean(label: 'Rounded'), + selected: context.knobs.boolean(label: 'Selected'), + onChange: context.knobs.boolean(label: 'Enabled') ? ({bool value = false}) {} : null, + ) + ], + ), ), ), ), WidgetbookUseCase( - name: 'Filter Chip', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: ChipExample.filterChipExample, + name: 'Assist Chip', + builder: (context) => TestWidget( + widget: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + ZetaChip.assist( + label: context.knobs.string(label: 'Label', initialValue: 'Label'), + rounded: context.knobs.boolean(label: 'Rounded'), + showIcon: context.knobs.boolean(label: 'Show Icon'), + icon: context.knobs.list( + label: 'Icon', + options: [ + Icon(ZetaIcons.star_half_round), + Icon(ZetaIcons.add_alert_round), + Icon(ZetaIcons.add_box_round), + Icon(ZetaIcons.barcode_round), + ], + labelBuilder: (value) { + if ((value as Icon).icon == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if ((value).icon == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if ((value).icon == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if ((value).icon == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + ), + ) + ], + ), ), ), ), WidgetbookUseCase( name: 'Status Chip', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: ChipExample.statusChipExample, + builder: (context) => TestWidget( + widget: Padding( + padding: const EdgeInsets.all(20), + child: Column(children: [ZetaChip.status(context.knobs.string(label: 'Label', initialValue: 'Label'))]), ), ), ), diff --git a/example/widgetbook/components/color_widgetbook.dart b/example/widgetbook/components/color_widgetbook.dart deleted file mode 100644 index a59acb93..00000000 --- a/example/widgetbook/components/color_widgetbook.dart +++ /dev/null @@ -1,130 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/color_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent colorWidgetBook() { - return WidgetbookComponent( - name: 'Colors', - useCases: [ - WidgetbookUseCase( - name: 'Colors', - builder: (BuildContext context) { - final colors = Zeta.of(context).colors; - - return LayoutBuilder( - builder: (context, constraints) { - 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 ZetaProvider( - builder: (context3, _, __) { - return Container( - padding: const EdgeInsets.symmetric(horizontal: Dimensions.l), - child: SingleChildScrollView( - child: Column( - children: [ - const SizedBox(height: Dimensions.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(Dimensions.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: Dimensions.l), - ], - ), - ), - ); - }, - ); - }, - ); - }, - ) - ], - ); -} diff --git a/example/widgetbook/components/in_page_banner_widgetbook.dart b/example/widgetbook/components/in_page_banner_widgetbook.dart deleted file mode 100644 index b5f69d96..00000000 --- a/example/widgetbook/components/in_page_banner_widgetbook.dart +++ /dev/null @@ -1,124 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/in_page_banner_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent inPageBannerWidgetBook() { - Widget _getTitle(String title) => Container( - height: 50, - child: Center(child: Text(title, style: ZetaTextStyles.titleLarge)), - ); - - ZetaWidgetColor _getCustomColors() => - ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue); - - return WidgetbookComponent( - name: 'InPageBanner', - useCases: [ - WidgetbookUseCase( - name: 'Default In Page Banner', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _getTitle('Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.neutral), - _getTitle('Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.neutral, border: BorderType.sharp), - ], - ), - ), - ), - ), - WidgetbookUseCase( - name: 'Info In Page Banner', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _getTitle('Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.info), - _getTitle('Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.info, border: BorderType.sharp), - ], - ), - ), - ), - ), - WidgetbookUseCase( - name: 'Positive In Page Banner', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _getTitle('Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.positive), - _getTitle('Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.positive, border: BorderType.sharp), - ], - ), - ), - ), - ), - WidgetbookUseCase( - name: 'Warning In Page Banner', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _getTitle('Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.warning), - _getTitle('Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.warning, border: BorderType.sharp), - ], - ), - ), - ), - ), - WidgetbookUseCase( - name: 'Negative In Page Banner', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _getTitle('Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.negative), - _getTitle('Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.negative, border: BorderType.sharp), - ], - ), - ), - ), - ), - WidgetbookUseCase( - name: 'Custom In Page Banner', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _getTitle('Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.custom, - customColors: _getCustomColors(), customIcon: ZetaIcons.alert_round), - _getTitle('Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.custom, - customColors: _getCustomColors(), border: BorderType.sharp, customIcon: ZetaIcons.alert_sharp), - ], - ), - ), - ), - ), - ], - ); -} diff --git a/example/widgetbook/components/indicator_widgetbook.dart b/example/widgetbook/components/indicator_widgetbook.dart deleted file mode 100644 index e73eadbe..00000000 --- a/example/widgetbook/components/indicator_widgetbook.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/indicator_example.dart'; - -WidgetbookComponent indicatorWidgetBook() { - return WidgetbookComponent( - name: 'Indicator', - useCases: [ - WidgetbookUseCase( - name: 'Icon', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: IndicatorExample.indicatorIconExample, - ), - ), - WidgetbookUseCase( - name: 'Notification', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: IndicatorExample.indicatorNotificationExample, - ), - ), - ], - ); -} diff --git a/example/widgetbook/components/menu_items_widgetbook.dart b/example/widgetbook/components/menu_items_widgetbook.dart deleted file mode 100644 index 6f391b32..00000000 --- a/example/widgetbook/components/menu_items_widgetbook.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/menu_items_example.dart'; - -WidgetbookComponent menuItemsWidgetBook() { - return WidgetbookComponent( - name: 'Menu Items', - useCases: [ - WidgetbookUseCase( - name: 'Horizontal', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: MenuItemsExample.horizontalExample, - ), - ), - WidgetbookUseCase( - name: 'Vertical', - builder: (context) => Padding( - padding: const EdgeInsets.all(20), - child: MenuItemsExample.verticalExample, - ), - ), - ], - ); -} diff --git a/example/widgetbook/components/password_input_widgetbook.dart b/example/widgetbook/components/password_input_widgetbook.dart index 937c59ec..649ac87a 100644 --- a/example/widgetbook/components/password_input_widgetbook.dart +++ b/example/widgetbook/components/password_input_widgetbook.dart @@ -1,50 +1,82 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/password_input_example.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; +import '../../test/test_components.dart'; + WidgetbookComponent passwordInputWidgetBook() { return WidgetbookComponent( name: 'Password Input', + isInitiallyExpanded: false, useCases: [ WidgetbookUseCase( - name: 'Rounded', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(Dimensions.x5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: Dimensions.x10), - ...passwordInputExampleRow(ZetaWidgetSize.large), - Divider(height: Dimensions.x20), - ...passwordInputExampleRow(ZetaWidgetSize.medium), - Divider(height: Dimensions.x20), - ...passwordInputExampleRow(ZetaWidgetSize.small), - ], - ), - ), - ), + name: 'Password Input', + builder: (context) { + return _Password(); + }, ), - WidgetbookUseCase( - name: 'Sharp', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(Dimensions.x5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: Dimensions.x10), - ...passwordInputExampleRow(ZetaWidgetSize.large, borderType: BorderType.sharp), - Divider(height: Dimensions.x20), - ...passwordInputExampleRow(ZetaWidgetSize.medium, borderType: BorderType.sharp), - Divider(height: Dimensions.x20), - ...passwordInputExampleRow(ZetaWidgetSize.small, borderType: BorderType.sharp), - ], - ), + ], + ); +} + +class _Password extends StatefulWidget { + const _Password(); + + @override + State<_Password> createState() => _PasswordState(); +} + +class _PasswordState extends State<_Password> { + final _passwordController = TextEditingController(); + final _formKey = GlobalKey(); + + @override + Widget build(BuildContext _) { + final enableValidation = context.knobs.boolean(label: 'Enable validation', initialValue: false); + final validationString = context.knobs.string(label: 'Error label', initialValue: 'Incorrect'); + return Form( + key: _formKey, + child: TestWidget( + widget: Padding( + padding: EdgeInsets.all(Dimensions.x5), + child: Column( + children: [ + ConstrainedBox( + constraints: BoxConstraints(maxWidth: 328), + child: ZetaPasswordInput( + borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + enabled: context.knobs.boolean(label: 'Enabled', initialValue: true), + obscureText: context.knobs.boolean(label: 'Obscure text', initialValue: true), + size: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), + footerIcon: context.knobs.listOrNull( + label: 'Icon', + options: [ + ZetaIcons.star_half_round, + ZetaIcons.add_alert_round, + ZetaIcons.add_box_round, + ZetaIcons.barcode_round, + ], + labelBuilder: (value) { + if (value == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if (value == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if (value == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if (value == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + initialOption: null, + ), + footerText: context.knobs.string(label: 'Footer Text'), + hintText: context.knobs.string(label: 'Hint text'), + label: context.knobs.string(label: 'Label'), + onChanged: (_) => _formKey.currentState?.validate(), + validator: (_) => enableValidation ? validationString : null, + controller: _passwordController, + ), + ), + ], ), ), ), - ], - ); + ); + } } diff --git a/example/widgetbook/components/priority_pill_widgetbook.dart b/example/widgetbook/components/priority_pill_widgetbook.dart deleted file mode 100644 index a7df83a8..00000000 --- a/example/widgetbook/components/priority_pill_widgetbook.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent priorityPillWidgetBook() { - return WidgetbookComponent( - name: 'PriorityPill', - useCases: [ - WidgetbookUseCase( - name: 'Priority Pill', - builder: (context) => SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ZetaPriorityPill( - index: 1, - priority: 'Priority', - borderType: BorderType.rounded, - ), - SizedBox(height: 50), - ZetaPriorityPill( - index: 2, - priority: 'Priority', - ) - ], - ), - ), - ), - ), - ], - ); -} diff --git a/example/widgetbook/components/status_label_widgetbook.dart b/example/widgetbook/components/status_label_widgetbook.dart deleted file mode 100644 index 6b5e61c3..00000000 --- a/example/widgetbook/components/status_label_widgetbook.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/status_label_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent statusLabelWidgetBook() { - return WidgetbookComponent( - name: 'StatusLabel', - useCases: [ - WidgetbookUseCase( - name: 'Status Label', - builder: (context) => SingleChildScrollView( - child: Column( - children: [ - statusLabelExampleRow(WidgetSeverity.neutral), - statusLabelExampleRow(WidgetSeverity.info), - statusLabelExampleRow(WidgetSeverity.positive), - statusLabelExampleRow(WidgetSeverity.warning), - statusLabelExampleRow(WidgetSeverity.negative), - statusLabelExampleRow( - WidgetSeverity.custom, - colors: ZetaWidgetColor(foregroundColor: Colors.blue, backgroundColor: Colors.blue.shade50), - ), - ], - ), - ), - ), - ], - ); -} diff --git a/example/widgetbook/components/tag_widgetbook.dart b/example/widgetbook/components/tag_widgetbook.dart deleted file mode 100644 index 091e59f5..00000000 --- a/example/widgetbook/components/tag_widgetbook.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/tag_example.dart'; - -WidgetbookComponent tagWidgetBook() { - return WidgetbookComponent( - name: 'Tag', - useCases: [ - WidgetbookUseCase( - name: 'Tag', - builder: (context) => Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [TagExample.tagsRowLeft, TagExample.tagsRowRight], - )), - ), - ], - ); -} diff --git a/example/widgetbook/components/workcloud_indicator_widgetbook.dart b/example/widgetbook/components/workcloud_indicator_widgetbook.dart deleted file mode 100644 index fbf000b4..00000000 --- a/example/widgetbook/components/workcloud_indicator_widgetbook.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/workcloud_indicator_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent workcloudIndicatorWidgetBook() { - return WidgetbookComponent( - name: 'Workcloud Indicator', - useCases: [ - WidgetbookUseCase( - name: 'Status', - builder: (context) => SingleChildScrollView( - child: Column( - children: [ - Row(children: [ - Padding( - padding: EdgeInsets.all(10), - child: ZetaWorkcloudIndicator.status(label: 'Status'), - ) - ]), - Row(children: [ - Padding( - padding: EdgeInsets.all(10), - child: ZetaWorkcloudIndicator.status(label: 'In Progress'), - ) - ]), - Row(children: [ - Padding( - padding: EdgeInsets.all(10), - child: ZetaWorkcloudIndicator.status(label: 'Reviewed'), - ) - ]), - Row(children: [ - Padding( - padding: EdgeInsets.all(10), - child: ZetaWorkcloudIndicator.status(label: 'Resolved'), - ) - ]), - ], - ), - ), - ), - WidgetbookUseCase( - name: 'Priority Pill', - builder: (context) => SingleChildScrollView( - child: Column( - children: [ - Padding( - padding: EdgeInsets.all(10), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [Text('Medium'), Text('Small'), Text('X-Small')], - ), - ), - workcloudIndicatorExampleRow('Urgent', 'U', ZetaWorkcloudIndicatorType.urgent), - workcloudIndicatorExampleRow('High', '1', ZetaWorkcloudIndicatorType.high), - workcloudIndicatorExampleRow('Medium', '2', ZetaWorkcloudIndicatorType.medium), - workcloudIndicatorExampleRow('Low', '3', ZetaWorkcloudIndicatorType.low), - workcloudIndicatorExampleRow('Custom', '4', ZetaWorkcloudIndicatorType.custom, - colors: - ZetaWidgetColor(backgroundColor: Colors.purple, foregroundColor: Colors.purple.shade50)), - ], - ), - )) - ], - ); -} diff --git a/example/widgetbook/theme/color_widgetbook.dart b/example/widgetbook/theme/color_widgetbook.dart new file mode 100644 index 00000000..dc0b1298 --- /dev/null +++ b/example/widgetbook/theme/color_widgetbook.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/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: Dimensions.l), + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: Dimensions.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(Dimensions.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: Dimensions.l), + ], + ), + ), + ); + }); + } +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 3f29b8d6..3417104f 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -4,20 +4,14 @@ import 'package:zeta_flutter/zeta_flutter.dart'; import 'components/accordion_widgetbook.dart'; import 'components/avatar_widgetbook.dart'; -import 'components/badge_widgetbook.dart'; +import 'components/badges_widgetbook.dart'; import 'components/bottom_sheet_widgetbook.dart'; import 'components/button_widgetbook.dart'; import 'components/checkbox_widgetbook.dart'; -import 'components/color_widgetbook.dart'; -import 'components/in_page_banner_widgetbook.dart'; -import 'components/indicator_widgetbook.dart'; +import 'theme/color_widgetbook.dart'; +import 'components/banner_widgetbook.dart'; import 'components/chip_widgetbook.dart'; -import 'components/menu_items_widgetbook.dart'; import 'components/password_input_widgetbook.dart'; -import 'components/priority_pill_widgetbook.dart'; -import 'components/status_label_widgetbook.dart'; -import 'components/tag_widgetbook.dart'; -import 'components/workcloud_indicator_widgetbook.dart'; import 'theme/typography_widgetbook.dart'; import 'utils/zebra.dart'; @@ -32,30 +26,25 @@ class HotReload extends StatelessWidget { directories: [ WidgetbookCategory( name: 'Components', + isInitiallyExpanded: false, children: [ - colorWidgetBook(), - statusLabelWidgetBook(), - tagWidgetBook(), badgeWidgetBook(), - indicatorWidgetBook(), - priorityPillWidgetBook(), - workcloudIndicatorWidgetBook(), avatarWidgetBook(), checkboxWidgetBook(), buttonWidgetBook(), - inPageBannerWidgetBook(), - menuItemsWidgetBook(), + BannerWidgetBook(), accordionWidgetBook(), chipWidgetBook(), - buttonWidgetBook(), passwordInputWidgetBook(), bottomSheetWidgetBook(), - ], + ]..sort((a, b) => a.name.compareTo(b.name)), ), WidgetbookCategory( name: 'Theme', + isInitiallyExpanded: false, children: [ textWidgetBook(), + colorWidgetBook(), ], ), ], diff --git a/lib/src/theme/tokens.dart b/lib/src/theme/tokens.dart index 0f46e869..c3c0fe56 100644 --- a/lib/src/theme/tokens.dart +++ b/lib/src/theme/tokens.dart @@ -1,4 +1,4 @@ -/// Tokens that are used for Spacing. +/// Tokens that are used for spacing. /// /// Values are doubles, and can be used for padding, margins and other spacings. /// diff --git a/pubspec.yaml b/pubspec.yaml index 678eecd8..e47fba44 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+21 +version: 0.1.1+22 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. From 2357d34d3b9401e4aea3d2b5ad763d7b576d0bb6 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Fri, 19 Jan 2024 17:03:41 +0000 Subject: [PATCH 32/41] chore: Tidy up example app (#53) https://jira.zebra.com/browse/UX-920 --------- Co-authored-by: github-actions --- CHANGELOG.md | 9 +- example/lib/home.dart | 94 ++- example/lib/pages/accordion_example.dart | 94 --- .../app_bar_example/app_bar_example.dart | 111 ---- .../app_bar_example/default_app_bar.dart | 24 - .../app_bar_example/negative_app_bar.dart | 26 - .../app_bar_example/positive_app_bar.dart | 25 - .../app_bar_example/warning_app_bar.dart | 25 - .../lib/pages/{ => assets}/icons_example.dart | 2 +- example/lib/pages/avatar_example.dart | 556 ------------------ example/lib/pages/badge_example.dart | 46 -- example/lib/pages/bottom_sheet.dart | 58 -- .../pages/components/accordion_example.dart | 94 +++ .../lib/pages/components/avatar_example.dart | 538 +++++++++++++++++ .../lib/pages/components/badges_example.dart | 308 ++++++++++ .../lib/pages/components/banner_example.dart | 178 ++++++ .../lib/pages/components/bottom_sheet.dart | 97 +++ .../{ => components}/button_example.dart | 168 +++++- .../{ => components}/checkbox_example.dart | 11 +- .../pages/{ => components}/chip_example.dart | 3 +- .../password_input_example.dart | 2 +- .../lib/pages/fab_example/fab_example.dart | 100 ---- .../lib/pages/fab_example/primary_fab.dart | 191 ------ example/lib/pages/in_page_banner_example.dart | 121 ---- example/lib/pages/indicator_example.dart | 176 ------ example/lib/pages/menu_items_example.dart | 112 ---- example/lib/pages/priority_pill_example.dart | 33 -- example/lib/pages/status_label_example.dart | 54 -- example/lib/pages/tag_example.dart | 49 -- .../lib/pages/{ => theme}/color_example.dart | 3 +- .../pages/workcloud_indicator_example.dart | 99 ---- example/lib/theme_service.dart | 2 +- .../{pages => utils}/theme_color_switch.dart | 0 .../theme_constrast_switch.dart | 0 .../{pages => utils}/theme_mode_switch.dart | 0 example/lib/widgets.dart | 7 +- example/pubspec.lock | 2 +- .../components/button_widgetbook.dart | 2 +- .../widgetbook/theme/color_widgetbook.dart | 2 +- pubspec.yaml | 2 +- 40 files changed, 1431 insertions(+), 1993 deletions(-) delete mode 100644 example/lib/pages/accordion_example.dart delete mode 100644 example/lib/pages/app_bar_example/app_bar_example.dart delete mode 100644 example/lib/pages/app_bar_example/default_app_bar.dart delete mode 100644 example/lib/pages/app_bar_example/negative_app_bar.dart delete mode 100644 example/lib/pages/app_bar_example/positive_app_bar.dart delete mode 100644 example/lib/pages/app_bar_example/warning_app_bar.dart rename example/lib/pages/{ => assets}/icons_example.dart (99%) delete mode 100644 example/lib/pages/avatar_example.dart delete mode 100644 example/lib/pages/badge_example.dart delete mode 100644 example/lib/pages/bottom_sheet.dart create mode 100644 example/lib/pages/components/accordion_example.dart create mode 100644 example/lib/pages/components/avatar_example.dart create mode 100644 example/lib/pages/components/badges_example.dart create mode 100644 example/lib/pages/components/banner_example.dart create mode 100644 example/lib/pages/components/bottom_sheet.dart rename example/lib/pages/{ => components}/button_example.dart (58%) rename example/lib/pages/{ => components}/checkbox_example.dart (84%) rename example/lib/pages/{ => components}/chip_example.dart (99%) rename example/lib/pages/{ => components}/password_input_example.dart (98%) delete mode 100644 example/lib/pages/fab_example/fab_example.dart delete mode 100644 example/lib/pages/fab_example/primary_fab.dart delete mode 100644 example/lib/pages/in_page_banner_example.dart delete mode 100644 example/lib/pages/indicator_example.dart delete mode 100644 example/lib/pages/menu_items_example.dart delete mode 100644 example/lib/pages/priority_pill_example.dart delete mode 100644 example/lib/pages/status_label_example.dart delete mode 100644 example/lib/pages/tag_example.dart rename example/lib/pages/{ => theme}/color_example.dart (99%) delete mode 100644 example/lib/pages/workcloud_indicator_example.dart rename example/lib/{pages => utils}/theme_color_switch.dart (100%) rename example/lib/{pages => utils}/theme_constrast_switch.dart (100%) rename example/lib/{pages => utils}/theme_mode_switch.dart (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index db163553..d41fc235 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [0.1.1+23] - 2024-01-19 +### :wrench: Chores +- [`ed1210d`](https://github.com/zebratechnologies/zeta-flutter/commit/ed1210d6cbc173aef8b1adf0d20ee91d3e87f2c3) - Update Widgetbook to correct functionality *(PR [#52](https://github.com/zebratechnologies/zeta-flutter/pull/52) by [@thelukewalton](https://github.com/thelukewalton))* +- [`c627d7a`](https://github.com/zebratechnologies/zeta-flutter/commit/c627d7ab19d3f33e30c406441702ff6134557f14) - Tidy up example app *(PR [#53](https://github.com/zebratechnologies/zeta-flutter/pull/53) by [@thelukewalton](https://github.com/thelukewalton))* + + ## [0.1.1+22] - 2024-01-19 ### :boom: BREAKING CHANGES - due to [`7b543ac`](https://github.com/zebratechnologies/zeta-flutter/commit/7b543ac7b92dc53a866af4de313c36b5728e912e) - Remove legacy code *(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))*: @@ -1751,4 +1757,5 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+19]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+18...0.1.1+19 [0.1.1+20]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+19...0.1.1+20 [0.1.1+21]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+20...0.1.1+21 -[0.1.1+22]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+21...0.1.1+22 \ No newline at end of file +[0.1.1+22]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+21...0.1.1+22 +[0.1.1+23]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+22...0.1.1+23 \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 4fb9360d..7a1fd347 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -1,30 +1,16 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:zeta_example/pages/accordion_example.dart'; -import 'package:zeta_example/pages/app_bar_example/app_bar_example.dart'; -import 'package:zeta_example/pages/app_bar_example/default_app_bar.dart'; -import 'package:zeta_example/pages/app_bar_example/negative_app_bar.dart'; -import 'package:zeta_example/pages/app_bar_example/positive_app_bar.dart'; -import 'package:zeta_example/pages/app_bar_example/warning_app_bar.dart'; -import 'package:zeta_example/pages/avatar_example.dart'; -import 'package:zeta_example/pages/badge_example.dart'; -import 'package:zeta_example/pages/bottom_sheet.dart'; -import 'package:zeta_example/pages/button_example.dart'; -import 'package:zeta_example/pages/color_example.dart'; -import 'package:zeta_example/pages/checkbox_example.dart'; -import 'package:zeta_example/pages/fab_example/fab_example.dart'; -import 'package:zeta_example/pages/fab_example/primary_fab.dart'; -import 'package:zeta_example/pages/chip_example.dart'; -import 'package:zeta_example/pages/menu_items_example.dart'; -import 'package:zeta_example/pages/in_page_banner_example.dart'; -import 'package:zeta_example/pages/password_input_example.dart'; -import 'package:zeta_example/pages/priority_pill_example.dart'; -import 'package:zeta_example/pages/icons_example.dart'; -import 'package:zeta_example/pages/indicator_example.dart'; -import 'package:zeta_example/pages/status_label_example.dart'; -import 'package:zeta_example/pages/tag_example.dart'; -import 'package:zeta_example/pages/theme/typography_example.dart'; -import 'package:zeta_example/pages/workcloud_indicator_example.dart'; +import 'package:zeta_example/pages/components/accordion_example.dart'; +import 'package:zeta_example/pages/components/avatar_example.dart'; +import 'package:zeta_example/pages/components/badges_example.dart'; +import 'package:zeta_example/pages/components/banner_example.dart'; +import 'package:zeta_example/pages/components/bottom_sheet.dart'; +import 'package:zeta_example/pages/components/button_example.dart'; +import 'package:zeta_example/pages/components/checkbox_example.dart'; +import 'package:zeta_example/pages/components/chip_example.dart'; +import 'package:zeta_example/pages/theme/color_example.dart'; +import 'package:zeta_example/pages/components/password_input_example.dart'; +import 'package:zeta_example/pages/assets/icons_example.dart'; import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; @@ -37,41 +23,22 @@ class Component { } final List components = [ - Component(ColorExample.name, (context) => const ColorExample()), - Component(AvatarExample.name, (context) => const AvatarExample()), - Component(IconsExample.name, (context) => const IconsExample()), - Component(IndicatorExample.name, (context) => const IndicatorExample()), - Component(LabelExample.name, (context) => const LabelExample()), - Component(TagExample.name, (context) => const TagExample()), - Component(BadgeExample.name, (context) => const BadgeExample()), - Component(PriorityPillExample.name, (context) => const PriorityPillExample()), - Component(WorkcloudIndicatorExample.name, (context) => const WorkcloudIndicatorExample()), - Component(AppBarExample.name, (context) => const AppBarExample(), [ - Component(DefaultAppBarExample.name, (context) => const DefaultAppBarExample()), - Component(PositiveAppBarExample.name, (context) => const PositiveAppBarExample()), - Component(WarningAppBarExample.name, (context) => const WarningAppBarExample()), - Component(NegativeAppBarExample.name, (context) => const NegativeAppBarExample()), - ]), - Component(CheckBoxExample.name, (context) => const CheckBoxExample()), - Component(InPageBannerExample.name, (context) => const InPageBannerExample()), Component(AccordionExample.name, (context) => const AccordionExample()), + Component(AvatarExample.name, (context) => const AvatarExample()), + Component(BannerExample.name, (context) => const BannerExample()), + Component(BadgesExample.name, (context) => const BadgesExample()), + Component(BottomSheetExample.name, (context) => const BottomSheetExample()), Component(ButtonExample.name, (context) => const ButtonExample()), - Component(FABExample.name, (context) => const FABExample(), [ - Component(FabPrimarySmallCircle.name, (context) => const FabPrimarySmallCircle()), - Component(FabPrimarySmallRounded.name, (context) => const FabPrimarySmallRounded()), - Component(FabPrimarySecondSmallSharp.name, (context) => const FabPrimarySecondSmallSharp()), - Component(FabPrimarySecondLargeCircle.name, (context) => const FabPrimarySecondLargeCircle()), - Component(FabInverseLargeRounded.name, (context) => const FabInverseLargeRounded()), - Component(FabInverseLargeSharp.name, (context) => const FabInverseLargeSharp()), - ]), - Component(MenuItemsExample.name, (context) => const MenuItemsExample()), + Component(CheckBoxExample.name, (context) => const CheckBoxExample()), Component(ChipExample.name, (context) => const ChipExample()), Component(PasswordInputExample.name, (context) => const PasswordInputExample()), - Component(BottomSheetExample.name, (context) => const BottomSheetExample()), ]; final List theme = [ - Component(TypographyExample.name, (context) => TypographyExample()), + Component(ColorExample.name, (context) => const ColorExample()), +]; +final List assets = [ + Component(IconsExample.name, (context) => const IconsExample()), ]; class Home extends StatefulWidget { @@ -88,13 +55,21 @@ final GoRouter router = GoRouter( name: 'Home', builder: (_, __) => const Home(), routes: [ - ...[...components, ...theme].map( + ...[ + ...components, + ...assets, + ...theme, + ].map( (e) => GoRoute( path: e.name, name: e.name, builder: (_, __) => e.pageBuilder.call(_), routes: e.children - .map((f) => GoRoute(path: f.name, name: f.name, builder: (_, __) => f.pageBuilder(_))) + .map((f) => GoRoute( + path: f.name, + name: f.name, + builder: (_, __) => f.pageBuilder(_), + )) .toList(), ), ) @@ -107,8 +82,8 @@ class _HomeState extends State { @override Widget build(BuildContext context) { final _components = components..sort((a, b) => a.name.compareTo(b.name)); + final _assets = assets..sort((a, b) => a.name.compareTo(b.name)); final _theme = theme..sort((a, b) => a.name.compareTo(b.name)); - return ExampleScaffold( name: 'Zeta', child: SingleChildScrollView( @@ -128,6 +103,13 @@ class _HomeState extends State { .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(), + ), ], ), ), diff --git a/example/lib/pages/accordion_example.dart b/example/lib/pages/accordion_example.dart deleted file mode 100644 index 67a12e43..00000000 --- a/example/lib/pages/accordion_example.dart +++ /dev/null @@ -1,94 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class AccordionExample extends StatelessWidget { - static const String name = 'Accordion'; - - const AccordionExample({super.key}); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: AccordionExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), - child: Column( - children: [ - Text('Default'), - const SizedBox(height: 20), - accordionDefaultExample, - const SizedBox(height: 40), - Text('Contained'), - const SizedBox(height: 20), - accordionContainedExample, - const SizedBox(height: 40), - Text('Sharp'), - const SizedBox(height: 20), - accordionSharpExample, - ], - ), - ), - ); - }, - ); - } - - static Widget get accordionDefaultExample => ZetaAccordion( - spaceBetween: 0, - children: [ - ZetaAccordionSection( - title: Text('Title Default Enabled'), - body: Column( - children: [ - ListTile(title: Text('List Item')), - ListTile(title: Text('List Item')), - ListTile(title: Text('List Item')), - ], - ), - ), - ZetaAccordionSection( - disabled: true, - title: Text('Title Default Disabled'), - body: Text('...'), - ), - ], - ); - - static Widget get accordionContainedExample => ZetaAccordion( - contained: true, - children: [ - ZetaAccordionSection( - title: Text('Title Contained Enabled'), - body: Text( - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'), - ), - ZetaAccordionSection( - disabled: true, - title: Text('Title Contained Disabled'), - body: Text('...'), - ), - ], - ); - - static Widget get accordionSharpExample => ZetaAccordion( - contained: true, - rounded: false, - children: [ - ZetaAccordionSection( - title: Text('Title Contained Sharp Enabled'), - body: Center( - child: Icon(Icons.image_outlined, size: 300), - ), - ), - ZetaAccordionSection( - disabled: true, - title: Text('Title Contained Sharp Disabled'), - body: Text('...'), - ), - ], - ); -} diff --git a/example/lib/pages/app_bar_example/app_bar_example.dart b/example/lib/pages/app_bar_example/app_bar_example.dart deleted file mode 100644 index 01deaac8..00000000 --- a/example/lib/pages/app_bar_example/app_bar_example.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_example/home.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; -import 'default_app_bar.dart'; -import '../../widgets.dart'; -import 'negative_app_bar.dart'; -import 'positive_app_bar.dart'; -import 'warning_app_bar.dart'; - -class AppBarExample extends StatelessWidget { - static const String name = 'AppBar'; - - const AppBarExample({super.key}); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: AppBarExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.symmetric(vertical: Dimensions.m), - child: Column( - children: [ - ZetaSystemBanner( - type: ZetaSystemBannerType.defaultAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - ), - const SizedBox(height: Dimensions.m), - ZetaSystemBanner( - type: ZetaSystemBannerType.positiveAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - titleIcon: Icon(ZetaIcons.info_round), - ), - const SizedBox(height: Dimensions.m), - ZetaSystemBanner( - type: ZetaSystemBannerType.warningAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - centerTitle: true, - ), - const SizedBox(height: Dimensions.m), - ZetaSystemBanner( - type: ZetaSystemBannerType.negativeAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - titleIcon: Icon(ZetaIcons.info_round), - centerTitle: true, - ), - const SizedBox(height: Dimensions.m), - ZetaSystemBanner( - type: ZetaSystemBannerType.defaultAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - actions: [ - IconButton( - onPressed: () => router.pushNamed(DefaultAppBarExample.name), - icon: Icon(ZetaIcons.chevron_right_round), - ), - ], - ), - const SizedBox(height: Dimensions.m), - ZetaSystemBanner( - type: ZetaSystemBannerType.positiveAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - titleIcon: Icon(ZetaIcons.info_round), - actions: [ - IconButton( - onPressed: () => router.pushNamed(PositiveAppBarExample.name), - icon: Icon(ZetaIcons.chevron_right_round), - ), - ], - ), - const SizedBox(height: Dimensions.m), - ZetaSystemBanner( - type: ZetaSystemBannerType.warningAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - centerTitle: true, - actions: [ - IconButton( - onPressed: () => router.pushNamed(WarningAppBarExample.name), - icon: Icon(ZetaIcons.chevron_right_round), - ), - ], - ), - const SizedBox(height: Dimensions.m), - ZetaSystemBanner( - type: ZetaSystemBannerType.negativeAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - titleIcon: Icon(ZetaIcons.info_round), - centerTitle: true, - actions: [ - IconButton( - onPressed: () => router.pushNamed(NegativeAppBarExample.name), - icon: Icon(ZetaIcons.chevron_right_round), - ), - ], - ), - ], - ), - ), - ); - }, - ); - } -} diff --git a/example/lib/pages/app_bar_example/default_app_bar.dart b/example/lib/pages/app_bar_example/default_app_bar.dart deleted file mode 100644 index 6a24ddbe..00000000 --- a/example/lib/pages/app_bar_example/default_app_bar.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:zeta_example/home.dart'; - -class DefaultAppBarExample extends StatelessWidget { - static const String name = 'DefaultAppBar'; - - const DefaultAppBarExample({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: ZetaSystemBanner( - type: ZetaSystemBannerType.defaultAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - leading: IconButton( - onPressed: () => router.pop(), - icon: Icon(ZetaIcons.chevron_left_round), - ), - ), - ); - } -} diff --git a/example/lib/pages/app_bar_example/negative_app_bar.dart b/example/lib/pages/app_bar_example/negative_app_bar.dart deleted file mode 100644 index 51d4cf7d..00000000 --- a/example/lib/pages/app_bar_example/negative_app_bar.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:zeta_example/home.dart'; - -class NegativeAppBarExample extends StatelessWidget { - static const String name = 'NegativeAppBar'; - - const NegativeAppBarExample({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: ZetaSystemBanner( - type: ZetaSystemBannerType.negativeAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - titleIcon: Icon(ZetaIcons.info_round), - centerTitle: true, - leading: IconButton( - onPressed: () => router.pop(), - icon: Icon(ZetaIcons.chevron_left_round), - ), - ), - ); - } -} diff --git a/example/lib/pages/app_bar_example/positive_app_bar.dart b/example/lib/pages/app_bar_example/positive_app_bar.dart deleted file mode 100644 index f2377a7d..00000000 --- a/example/lib/pages/app_bar_example/positive_app_bar.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:zeta_example/home.dart'; - -class PositiveAppBarExample extends StatelessWidget { - static const String name = 'PositiveAppBar'; - - const PositiveAppBarExample({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: ZetaSystemBanner( - type: ZetaSystemBannerType.positiveAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - titleIcon: Icon(ZetaIcons.info_round), - leading: IconButton( - onPressed: () => router.pop(), - icon: Icon(ZetaIcons.chevron_left_round), - ), - ), - ); - } -} diff --git a/example/lib/pages/app_bar_example/warning_app_bar.dart b/example/lib/pages/app_bar_example/warning_app_bar.dart deleted file mode 100644 index 22db2f9a..00000000 --- a/example/lib/pages/app_bar_example/warning_app_bar.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:zeta_example/home.dart'; - -class WarningAppBarExample extends StatelessWidget { - static const String name = 'WarningAppBar'; - - const WarningAppBarExample({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: ZetaSystemBanner( - type: ZetaSystemBannerType.warningAppBar, - automaticallyImplyLeading: false, - title: Text('Banner Title'), - centerTitle: true, - leading: IconButton( - onPressed: () => router.pop(), - icon: Icon(ZetaIcons.chevron_left_round), - ), - ), - ); - } -} diff --git a/example/lib/pages/icons_example.dart b/example/lib/pages/assets/icons_example.dart similarity index 99% rename from example/lib/pages/icons_example.dart rename to example/lib/pages/assets/icons_example.dart index 2e82bc9b..182a2430 100644 --- a/example/lib/pages/icons_example.dart +++ b/example/lib/pages/assets/icons_example.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../widgets.dart'; +import '../../widgets.dart'; class IconsExample extends StatefulWidget { static const String name = 'Icons'; diff --git a/example/lib/pages/avatar_example.dart b/example/lib/pages/avatar_example.dart deleted file mode 100644 index a3bef6e5..00000000 --- a/example/lib/pages/avatar_example.dart +++ /dev/null @@ -1,556 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class AvatarExample extends StatelessWidget { - static const String name = 'Avatar'; - - const AvatarExample({super.key}); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: AvatarExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), - child: Column( - children: [ - avatarImageExample, - const SizedBox(height: 25), - avatarInitialsExample, - const SizedBox(height: 25), - avatarImageWithBadgeExample, - const SizedBox(height: 25), - avatarInitialsWithBadgeExample, - const SizedBox(height: 25), - avatarImageWithSpecialStatusExample, - const SizedBox(height: 25), - avatarInitialsWithSpecialStatusExample, - ], - ), - ), - ); - }, - ); - } - - static Widget get avatarImageExample => Column( - children: [ - Text( - 'ZetaAvatar.image', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size); - final padding = (ZetaAvatar.getSizePixels(size) - 14) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), - ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image(size: size), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], - ), - ], - ); - - static Widget get avatarInitialsExample => Column( - children: [ - Text( - 'ZetaAvatar.initials', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size); - final padding = (ZetaAvatar.getSizePixels(size) - 14) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), - ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - initials: 'AB', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - name: 'Antony Brothers', - showStatus: true, - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], - ), - ], - ); - - static Widget get avatarImageWithBadgeExample => Column( - children: [ - Text( - 'ZetaAvatar.image with badge', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size) + 6; - final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), - ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], - ), - ], - ); - - static Widget get avatarInitialsWithBadgeExample => Column( - children: [ - Text( - 'ZetaAvatar.initials with badge', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size) + 6; - final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), - ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - initials: 'AB', - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - name: 'Antony Brothers', - showStatus: true, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], - ), - ], - ); - - static Widget get avatarImageWithSpecialStatusExample => Column( - children: [ - Text( - 'ZetaAvatar.image with special status', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size) + 6; - final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), - ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], - ), - ], - ); - - static Widget get avatarInitialsWithSpecialStatusExample => Column( - children: [ - Text( - 'ZetaAvatar.initials with special status', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size) + 6; - final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), - ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - initials: 'AB', - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - name: 'Antony Brothers', - showStatus: true, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], - ), - ], - ); - - static ZetaIndicatorSize _getBadgeSize(ZetaAvatarSize size) { - switch (size) { - case ZetaAvatarSize.xl: - return ZetaIndicatorSize.large; - case ZetaAvatarSize.l: - return ZetaIndicatorSize.large; - case ZetaAvatarSize.m: - return ZetaIndicatorSize.large; - case ZetaAvatarSize.s: - return ZetaIndicatorSize.medium; - case ZetaAvatarSize.xs: - return ZetaIndicatorSize.small; - } - } - - static ZetaIndicatorSize _getSpecialStatusSize(ZetaAvatarSize size) { - switch (size) { - case ZetaAvatarSize.xl: - return ZetaIndicatorSize.large; - case ZetaAvatarSize.l: - return ZetaIndicatorSize.medium; - case ZetaAvatarSize.m: - return ZetaIndicatorSize.medium; - case ZetaAvatarSize.s: - return ZetaIndicatorSize.medium; - case ZetaAvatarSize.xs: - return ZetaIndicatorSize.small; - } - } -} diff --git a/example/lib/pages/badge_example.dart b/example/lib/pages/badge_example.dart deleted file mode 100644 index 1dbac310..00000000 --- a/example/lib/pages/badge_example.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class BadgeExample extends StatelessWidget { - static const String name = 'Badge'; - - const BadgeExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ExampleScaffold( - name: BadgeExample.name, - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - badgeExampleRow(WidgetSeverity.info), - badgeExampleRow(WidgetSeverity.positive), - badgeExampleRow(WidgetSeverity.warning), - badgeExampleRow(WidgetSeverity.negative), - badgeExampleRow(WidgetSeverity.neutral), - ], - ), - ), - ); - } -} - -Widget badgeExampleRow(WidgetSeverity type) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - ZetaBadge( - label: 'Label', - severity: type, - borderType: BorderType.sharp, - ), - ZetaBadge( - label: 'Label', - severity: type, - ), - ]); -} diff --git a/example/lib/pages/bottom_sheet.dart b/example/lib/pages/bottom_sheet.dart deleted file mode 100644 index 8df661db..00000000 --- a/example/lib/pages/bottom_sheet.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class BottomSheetExample extends StatelessWidget { - static const String name = 'BottomSheet'; - - const BottomSheetExample({super.key}); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: BottomSheetExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), - child: Column( - children: [ - bottomSheet(context), - bottomSheet(context, Alignment.centerLeft), - ], - ), - ), - ); - }, - ); - } - - static bottomSheet(BuildContext context, [AlignmentGeometry? alignment]) => ZetaMenuItem.horizontal( - label: Text('Bottom Sheet - ${alignment ?? Alignment.center}'), - trailingIcon: Icon(ZetaIcons.caret_down_round), - onTap: () { - showModalBottomSheet( - context: context, - builder: (BuildContext context) { - return ZetaBottomSheet( - title: 'Bottom Sheet', - titleAlignment: alignment, - body: Wrap( - spacing: 12, - runSpacing: 12, - children: List.generate( - 6, - (index) => ZetaMenuItem.vertical( - label: Text('Menu Item'), - icon: Icon(ZetaIcons.star_round), - onTap: () {}, - ), - ), - ), - ); - }, - ); - }, - ); -} diff --git a/example/lib/pages/components/accordion_example.dart b/example/lib/pages/components/accordion_example.dart new file mode 100644 index 00000000..0c52a2c2 --- /dev/null +++ b/example/lib/pages/components/accordion_example.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class AccordionExample extends StatelessWidget { + static const String name = 'Accordion'; + + const AccordionExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: AccordionExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + Text('Rounded Divider'), + const SizedBox(height: 20), + ZetaAccordion( + children: [ + ZetaAccordionSection( + title: Text('Title Default Enabled'), + body: Column( + children: [ + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ], + ), + ), + ZetaAccordionSection(disabled: true, title: Text('Title Default Disabled'), body: Text('...')), + ], + ), + const SizedBox(height: 40), + Text('Rounded Contained'), + const SizedBox(height: 20), + ZetaAccordion( + contained: true, + children: [ + ZetaAccordionSection( + title: Text('Title Contained Enabled'), + body: Column( + children: [ + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ], + ), + ), + ZetaAccordionSection(disabled: true, title: Text('Title Contained Disabled'), body: Text('...')), + ], + ), + const SizedBox(height: 40), + Text('Sharp Divider'), + const SizedBox(height: 20), + ZetaAccordion( + contained: false, + rounded: false, + children: [ + ZetaAccordionSection( + title: Text('Title Contained Sharp Enabled'), + body: Center(child: Icon(Icons.image_outlined, size: 300)), + ), + ZetaAccordionSection( + disabled: true, + title: Text('Title Contained Sharp Disabled'), + body: Text('...'), + ), + ], + ), + Text('Sharp Contained'), + const SizedBox(height: 20), + ZetaAccordion( + contained: true, + rounded: false, + children: [ + ZetaAccordionSection( + title: Text('Title'), + body: Center(child: Icon(Icons.image_outlined, size: 300)), + ), + ZetaAccordionSection(disabled: true, title: Text('Title'), body: Text('...')), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/example/lib/pages/components/avatar_example.dart b/example/lib/pages/components/avatar_example.dart new file mode 100644 index 00000000..a8b3a3b3 --- /dev/null +++ b/example/lib/pages/components/avatar_example.dart @@ -0,0 +1,538 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class AvatarExample extends StatelessWidget { + static const String name = 'Avatar'; + + const AvatarExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: AvatarExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + Column( + children: [ + Text( + 'ZetaAvatar.image', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size); + final padding = (ZetaAvatar.getSizePixels(size) - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image(size: size), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.initials', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size); + final padding = (ZetaAvatar.getSizePixels(size) - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + name: 'Antony Brothers', + showStatus: true, + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.image with badge', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size) + 6; + final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.initials with badge', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size) + 6; + final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + name: 'Antony Brothers', + showStatus: true, + badge: ZetaIndicator.notification( + value: 3, + size: _getBadgeSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.image with special status', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size) + 6; + final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + showStatus: true, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.initials with special status', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = ZetaAvatar.getSizePixels(size) + 6; + final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + name: 'Antony Brothers', + showStatus: true, + specialStatus: ZetaIndicator.icon( + size: _getSpecialStatusSize(size), + ), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ), + ].divide(const SizedBox(height: Dimensions.x6)).toList(), + ), + ), + ); + }, + ); + } + + static ZetaIndicatorSize _getBadgeSize(ZetaAvatarSize size) { + switch (size) { + case ZetaAvatarSize.xl: + return ZetaIndicatorSize.large; + case ZetaAvatarSize.l: + return ZetaIndicatorSize.large; + case ZetaAvatarSize.m: + return ZetaIndicatorSize.large; + case ZetaAvatarSize.s: + return ZetaIndicatorSize.medium; + case ZetaAvatarSize.xs: + return ZetaIndicatorSize.small; + } + } + + static ZetaIndicatorSize _getSpecialStatusSize(ZetaAvatarSize size) { + switch (size) { + case ZetaAvatarSize.xl: + return ZetaIndicatorSize.large; + case ZetaAvatarSize.l: + return ZetaIndicatorSize.medium; + case ZetaAvatarSize.m: + return ZetaIndicatorSize.medium; + case ZetaAvatarSize.s: + return ZetaIndicatorSize.medium; + case ZetaAvatarSize.xs: + return ZetaIndicatorSize.small; + } + } +} diff --git a/example/lib/pages/components/badges_example.dart b/example/lib/pages/components/badges_example.dart new file mode 100644 index 00000000..b7fe49ab --- /dev/null +++ b/example/lib/pages/components/badges_example.dart @@ -0,0 +1,308 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class BadgesExample extends StatelessWidget { + static const String name = 'Badges'; + + const BadgesExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: BadgesExample.name, + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _DividingText('Status Label'), + _StatusLabel(), + _DividingText('Priority Pill'), + _PriorityPill(), + _DividingText('Badge'), + _Badge(), + _DividingText('Indicators'), + _Indicators(), + _DividingText('Tags'), + _Tags(), + _DividingText('WorkCloud indicators'), + _WorkcloudIndicators(), + ], + ), + ), + ); + } +} + +class _DividingText extends StatelessWidget { + final String text; + const _DividingText(this.text); + + @override + Widget build(BuildContext context) { + return Text( + text, + style: ZetaTextStyles.displayMedium, + ).paddingVertical(Dimensions.l); + } +} + +class _StatusLabel extends StatelessWidget { + const _StatusLabel(); + + Widget statusLabelExampleRow(WidgetSeverity type, {ZetaWidgetColor? colors}) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ZetaStatusLabel(label: 'Label', severity: type, isDefaultIcon: false, customColors: colors), + ZetaStatusLabel(label: 'Label', severity: type, borderType: BorderType.rounded, customColors: colors), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + statusLabelExampleRow(WidgetSeverity.neutral), + statusLabelExampleRow(WidgetSeverity.info), + statusLabelExampleRow(WidgetSeverity.positive), + statusLabelExampleRow(WidgetSeverity.warning), + statusLabelExampleRow(WidgetSeverity.negative), + statusLabelExampleRow( + WidgetSeverity.custom, + colors: ZetaWidgetColor(foregroundColor: Colors.blue, backgroundColor: Colors.blue.shade50), + ) + ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ); + } +} + +class _PriorityPill extends StatelessWidget { + const _PriorityPill(); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + ZetaPriorityPill(index: 1, priority: 'Rounded', borderType: BorderType.rounded), + ZetaPriorityPill(index: 2, priority: 'Sharp'), + ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ); + } +} + +class _Badge extends StatelessWidget { + const _Badge(); + + Widget badgeExampleRow(WidgetSeverity type) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ZetaBadge(label: 'Label', severity: type, borderType: BorderType.sharp), + ZetaBadge(label: 'Label', severity: type), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + badgeExampleRow(WidgetSeverity.info), + badgeExampleRow(WidgetSeverity.positive), + badgeExampleRow(WidgetSeverity.warning), + badgeExampleRow(WidgetSeverity.negative), + badgeExampleRow(WidgetSeverity.neutral), + ].divide(const SizedBox(height: Dimensions.m)).toList(), + ); + } +} + +class _Indicators extends StatelessWidget { + const _Indicators(); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Column( + children: [ + Text( + 'ZetaIndicator.icon', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + ZetaIndicator.icon(), + ZetaIndicator.icon(size: ZetaIndicatorSize.medium), + ZetaIndicator.icon(size: ZetaIndicatorSize.small), + ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ), + Row( + children: [ + ZetaIndicator.icon(inverseBorder: true), + ZetaIndicator.icon(size: ZetaIndicatorSize.medium, inverseBorder: true), + ZetaIndicator.icon(size: ZetaIndicatorSize.small, inverseBorder: true), + ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ), + Text('Rounded', style: TextStyle(fontWeight: FontWeight.bold)), + ].divide(const SizedBox.square(dimension: Dimensions.xs)).toList(), + ), + const SizedBox(width: 50), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + ZetaIndicator.icon(rounded: false), + ZetaIndicator.icon(size: ZetaIndicatorSize.medium, rounded: false), + ZetaIndicator.icon(size: ZetaIndicatorSize.small), + ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ), + Row( + children: [ + ZetaIndicator.icon(rounded: false, inverseBorder: true), + ZetaIndicator.icon(size: ZetaIndicatorSize.medium, rounded: false, inverseBorder: true), + ZetaIndicator.icon(size: ZetaIndicatorSize.small, inverseBorder: true), + ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ), + Text('Sharp', style: TextStyle(fontWeight: FontWeight.bold)), + ].divide(const SizedBox.square(dimension: Dimensions.s)).toList(), + ), + ], + ), + ], + ), + const SizedBox.square(dimension: Dimensions.xl), + Column( + children: [ + Text('ZetaIndicator.notification', style: TextStyle(fontWeight: FontWeight.bold)), + const SizedBox(height: 15), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + ZetaIndicator.notification(value: 3), + ZetaIndicator.notification(size: ZetaIndicatorSize.medium, value: 3), + ZetaIndicator.notification(size: ZetaIndicatorSize.small), + ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ), + Row( + children: [ + ZetaIndicator.notification(value: 3, inverseBorder: true), + ZetaIndicator.notification(size: ZetaIndicatorSize.medium, value: 3, inverseBorder: true), + ZetaIndicator.notification(size: ZetaIndicatorSize.small, inverseBorder: true), + ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ), + Text('', style: TextStyle(fontWeight: FontWeight.bold)), + ].divide(const SizedBox.square(dimension: Dimensions.s)).toList(), + ), + ], + ), + ], + ), + ], + ); + } +} + +class _Tags extends StatelessWidget { + const _Tags(); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + ZetaTag.left(label: 'Sharp', borderType: BorderType.sharp), + ZetaTag.right(label: 'Sharp', borderType: BorderType.sharp), + ZetaTag.left(label: 'Rounded', borderType: BorderType.sharp), + ZetaTag.right(label: 'Rounded', borderType: BorderType.rounded), + ].divide(SizedBox.square(dimension: Dimensions.m)).toList(), + ); + } +} + +class _WorkcloudIndicators extends StatelessWidget { + const _WorkcloudIndicators(); + + List workcloudIndicatorStatusRow(String label) { + return [ + Row(children: [ZetaWorkcloudIndicator.status(label: label)]), + SizedBox(height: 10) + ]; + } + + Widget workcloudIndicatorExampleRow(String label, String index, ZetaWorkcloudIndicatorType type, + {ZetaWidgetColor? colors}) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ZetaWorkcloudIndicator.priorityPill( + index: index, label: label, priorityType: type, prioritySize: ZetaWidgetSize.large, customColors: colors), + ZetaWorkcloudIndicator.priorityPill( + index: index, + label: label, + prioritySize: ZetaWidgetSize.medium, + priorityType: type, + customColors: colors, + ), + ZetaWorkcloudIndicator.priorityPill(index: index, label: label, priorityType: type, customColors: colors), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ZetaWorkcloudIndicator(label: 'Test Status Badge'), + ZetaWorkcloudIndicator.status(label: 'Status'), + ZetaWorkcloudIndicator.status(label: 'In Progress'), + ZetaWorkcloudIndicator.status(label: 'Reviewed'), + ZetaWorkcloudIndicator.status(label: 'Resolved') + ].divide(const SizedBox.square(dimension: Dimensions.s)).toList(), + ), + SizedBox(height: 30), + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [Text('Medium'), Text('Small'), Text('X-Small')], + ), + workcloudIndicatorExampleRow('Urgent', 'U', ZetaWorkcloudIndicatorType.urgent), + workcloudIndicatorExampleRow('High', '1', ZetaWorkcloudIndicatorType.high), + workcloudIndicatorExampleRow('Medium', '2', ZetaWorkcloudIndicatorType.medium), + workcloudIndicatorExampleRow('Low', '3', ZetaWorkcloudIndicatorType.low), + workcloudIndicatorExampleRow( + 'Custom', + '4', + ZetaWorkcloudIndicatorType.custom, + colors: ZetaWidgetColor(backgroundColor: Colors.purple, foregroundColor: Colors.purple.shade50), + ), + ].divide(const SizedBox.square(dimension: Dimensions.s)).toList(), + ).paddingAll(Dimensions.m) + ], + ); + } +} diff --git a/example/lib/pages/components/banner_example.dart b/example/lib/pages/components/banner_example.dart new file mode 100644 index 00000000..02e35209 --- /dev/null +++ b/example/lib/pages/components/banner_example.dart @@ -0,0 +1,178 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class BannerExample extends StatelessWidget { + static const String name = 'Banner'; + + const BannerExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: BannerExample.name, + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('System Banner', style: ZetaTextStyles.displayMedium), + _getTitle('Style variants'), + ZetaSystemBanner( + type: ZetaSystemBannerType.defaultAppBar, + title: Text('Centered'), + centerTitle: true, + titleIcon: Icon(ZetaIcons.info_round), + ), + ZetaSystemBanner( + type: ZetaSystemBannerType.defaultAppBar, + title: Text('Title Left'), + ), + ZetaSystemBanner( + type: ZetaSystemBannerType.defaultAppBar, + title: Text('Title left with arrow'), + centerTitle: true, + actions: [Icon(ZetaIcons.chevron_right_round)], + ), + ZetaSystemBanner( + type: ZetaSystemBannerType.defaultAppBar, + title: Text('Title left + Icon'), + centerTitle: true, + titleIcon: Icon(ZetaIcons.info_round), + ), + ZetaSystemBanner( + type: ZetaSystemBannerType.defaultAppBar, + title: Text('Title left + Icon with Arrow'), + centerTitle: true, + titleIcon: Icon(ZetaIcons.info_round), + actions: [Icon(ZetaIcons.chevron_right_round)], + ), + _getTitle('Color variants'), + ZetaSystemBanner( + type: ZetaSystemBannerType.positiveAppBar, + title: Text('Centered'), + centerTitle: true, + titleIcon: Icon(ZetaIcons.info_round), + ), + ZetaSystemBanner( + type: ZetaSystemBannerType.warningAppBar, + title: Text('Centered'), + centerTitle: true, + titleIcon: Icon(ZetaIcons.info_round), + ), + ZetaSystemBanner( + type: ZetaSystemBannerType.negativeAppBar, + title: Text('Centered'), + centerTitle: true, + titleIcon: Icon(ZetaIcons.info_round), + ), + const SizedBox(height: Dimensions.m), + const Divider(), + Text('In-Page Banner', style: ZetaTextStyles.displayMedium), + _getTitle('Default Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.neutral), + _getTitle('Info Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.info), + _getTitle('Positive Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.positive), + _getTitle('Warning Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.warning), + _getTitle('Negative Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.negative), + _getTitle('Custom Banner Rounded'), + buildExampleBannerColumn(WidgetSeverity.custom, + customColors: ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue)), + Divider( + height: 50, + color: Colors.transparent, + ), + _getTitle('Default Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.neutral, border: BorderType.sharp), + _getTitle('Info Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.info, border: BorderType.sharp), + _getTitle('Positive Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.positive, border: BorderType.sharp), + _getTitle('Warning Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.warning, border: BorderType.sharp), + _getTitle('Negative Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.negative, border: BorderType.sharp), + _getTitle('Custom Banner Sharp'), + buildExampleBannerColumn(WidgetSeverity.custom, + border: BorderType.sharp, + customColors: ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue)), + ] + .divide(const SizedBox( + height: 10, + )) + .toList(), + ), + ), + ), + ); + } + + final _content = 'Lorem ipsum dolor sit amet, conse ctetur cididunt ut' + 'labore et do lore magna aliqua.'; + + Widget _getTitle(String title) => Container(height: 50, child: Center(child: Text(title))); + + _getExampleBanner( + WidgetSeverity severity, + BorderType type, { + String? title, + bool showCloseBtn = true, + bool showFirstButton = false, + bool showSecondButton = false, + ZetaWidgetColor? customColors, + IconData? customIcon, + }) => + ZetaInPageBanner( + content: Text(_content), + onClose: () {}, + borderType: type, + severity: severity, + showIconClose: showCloseBtn, + title: title, + firstButton: showFirstButton ? ZetaPageBannerButton(label: 'Button', onPressed: () {}) : null, + secondButton: showSecondButton ? ZetaPageBannerButton(label: 'Button', onPressed: () {}) : null, + customColors: customColors, + customIcon: customIcon, + ); + + Column buildExampleBannerColumn( + WidgetSeverity severity, { + ZetaWidgetColor? customColors, + BorderType border = BorderType.rounded, + IconData? customIcon, + }) { + const _title = 'Banner Title'; + return Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + mainAxisSize: MainAxisSize.min, + children: [ + _getExampleBanner(severity, border, + title: _title, + showFirstButton: true, + showSecondButton: true, + customColors: customColors, + customIcon: customIcon), + _getExampleBanner(severity, border, title: _title, customColors: customColors, customIcon: customIcon), + Divider(color: Colors.transparent), + _getExampleBanner(severity, border, customColors: customColors, customIcon: customIcon), + Divider(color: Colors.transparent), + _getExampleBanner( + severity, + border, + showCloseBtn: false, + title: _title, + customColors: customColors, + customIcon: customIcon, + ), + Divider(color: Colors.transparent), + _getExampleBanner(severity, border, showCloseBtn: false, customColors: customColors, customIcon: customIcon), + Divider(), + ], + ); + } +} diff --git a/example/lib/pages/components/bottom_sheet.dart b/example/lib/pages/components/bottom_sheet.dart new file mode 100644 index 00000000..80258b51 --- /dev/null +++ b/example/lib/pages/components/bottom_sheet.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class BottomSheetExample extends StatelessWidget { + static const String name = 'BottomSheet'; + + const BottomSheetExample({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return ExampleScaffold( + name: BottomSheetExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(Dimensions.s), + child: Column( + children: [ + ZetaMenuItem.horizontal( + label: Text('Grid'), + onTap: () { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return ZetaBottomSheet( + title: 'Bottom Sheet', + titleAlignment: Alignment.centerLeft, + body: Wrap( + spacing: 12, + runSpacing: 12, + children: List.generate( + 6, + (index) => ZetaMenuItem.vertical( + label: Text('Menu Item'), + icon: Icon(ZetaIcons.star_round), + onTap: () {}, + ), + ), + ), + ); + }, + ); + }, + ), + ZetaMenuItem.horizontal( + label: Text('Horizontal'), + onTap: () { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return ZetaBottomSheet( + title: 'Bottom Sheet', + titleAlignment: Alignment.centerLeft, + body: Wrap( + spacing: 12, + runSpacing: 12, + children: List.generate( + 6, + (index) => ZetaMenuItem.horizontal(label: Text('Menu Item'), onTap: () {}), + ), + ), + ); + }, + ); + }, + ), + ZetaMenuItem.horizontal( + label: Text('With center title'), + onTap: () { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return ZetaBottomSheet( + title: 'Bottom Sheet', + horizontalAlignment: CrossAxisAlignment.center, + body: Wrap( + spacing: 12, + runSpacing: 12, + children: List.generate( + 6, + (index) => ZetaMenuItem.horizontal(label: Text('Menu Item'), onTap: () {}), + ), + ), + ); + }, + ); + }, + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/example/lib/pages/button_example.dart b/example/lib/pages/components/button_example.dart similarity index 58% rename from example/lib/pages/button_example.dart rename to example/lib/pages/components/button_example.dart index 3316eff4..6b875886 100644 --- a/example/lib/pages/button_example.dart +++ b/example/lib/pages/components/button_example.dart @@ -1,26 +1,167 @@ import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../widgets.dart'; - -class ButtonExample extends StatelessWidget { +class ButtonExample extends StatefulWidget { static const String name = 'Button'; const ButtonExample({super.key}); + @override + State createState() => _ButtonExampleState(); +} + +class _ButtonExampleState extends State { + Widget? fab; + late ScrollController _scrollController; + + @override + void initState() { + super.initState(); + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + void setFab(int index) => setState(() => fab = fabs[index]); + + List fabs = []; @override Widget build(BuildContext context) { + if (fabs.isEmpty) { + fabs = [ + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Small Circle Primary', + buttonSize: ZetaFabSize.small, + buttonShape: ZetaFabShape.circle, + buttonType: ZetaFabType.primary, + onPressed: () => setFab(0), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Small Rounded Primary', + buttonSize: ZetaFabSize.small, + buttonShape: ZetaFabShape.rounded, + buttonType: ZetaFabType.primary, + onPressed: () => setFab(1), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Small Sharp Primary', + buttonSize: ZetaFabSize.small, + buttonShape: ZetaFabShape.sharp, + buttonType: ZetaFabType.primary, + onPressed: () => setFab(2), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Small Circle Secondary', + buttonSize: ZetaFabSize.small, + buttonShape: ZetaFabShape.circle, + buttonType: ZetaFabType.primarySecond, + onPressed: () => setFab(3), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Small Circle Secondary', + buttonSize: ZetaFabSize.small, + buttonShape: ZetaFabShape.rounded, + buttonType: ZetaFabType.primarySecond, + onPressed: () => setFab(4), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Small Sharp Secondary', + buttonSize: ZetaFabSize.small, + buttonShape: ZetaFabShape.sharp, + buttonType: ZetaFabType.primarySecond, + onPressed: () => setFab(5), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Large Circle Primary', + buttonSize: ZetaFabSize.large, + buttonShape: ZetaFabShape.circle, + buttonType: ZetaFabType.primary, + onPressed: () => setFab(6), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Large Rounded Primary', + buttonSize: ZetaFabSize.large, + buttonShape: ZetaFabShape.rounded, + buttonType: ZetaFabType.primary, + onPressed: () => setFab(7), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Large Sharp Primary', + buttonSize: ZetaFabSize.large, + buttonShape: ZetaFabShape.sharp, + buttonType: ZetaFabType.primary, + onPressed: () => setFab(8), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Large Circle Primary', + buttonSize: ZetaFabSize.large, + buttonShape: ZetaFabShape.circle, + buttonType: ZetaFabType.primarySecond, + onPressed: () => setFab(9), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Large Rounded Secondary', + buttonSize: ZetaFabSize.large, + buttonShape: ZetaFabShape.rounded, + buttonType: ZetaFabType.primarySecond, + onPressed: () => setFab(10), + ), + ZetaFAB( + scrollController: _scrollController, + buttonLabel: 'Large Sharp Secondary', + buttonSize: ZetaFabSize.large, + buttonShape: ZetaFabShape.sharp, + buttonType: ZetaFabType.primarySecond, + onPressed: () => setFab(11), + ), + ]; + } final theme = Zeta.of(context); final colors = BuildExampleButtonColors(theme: theme); return ExampleScaffold( name: 'Button', - child: Padding( - padding: EdgeInsets.all(10), - child: SingleChildScrollView( - child: Column( - children: [roundedButtonsExample(colors), Divider(), Divider(), sharpButtonsExample(colors)], - ), + floatingActionButton: fab ?? fabs.first, + child: SingleChildScrollView( + controller: _scrollController, + child: Row( + children: [ + Expanded( + flex: 8, + child: Column( + children: [ + Text('Rounded Buttons', style: ZetaTextStyles.displayMedium), + roundedButtonsExample(colors), + Divider(), + Divider(), + Text('Sharp Buttons', style: ZetaTextStyles.displayMedium), + sharpButtonsExample(colors), + Divider(), + Divider(), + Text('Floating Action Buttons', style: ZetaTextStyles.displayMedium), + Text('Tap buttons to change current FAB: ', style: ZetaTextStyles.bodyMedium), + Wrap(children: fabs.divide(SizedBox.square(dimension: 10)).toList()), + ], + ), + ), + Expanded(child: const SizedBox()), + ], ), ), ); @@ -73,22 +214,20 @@ Widget sharpButtonsExample(BuildExampleButtonColors colors) => Column( List _getZetaButtonExampleRows(String label, ZetaButtonColors colors, {IconData? icon, ZetaButtonType buttonType = ZetaButtonType.filled, BorderType border = BorderType.rounded}) { return [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [Text('Large $label', style: ZetaTextStyles.titleLarge)]), + Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text('Large $label')]), Divider(color: Colors.transparent), _getRow(buttonType, ZetaWidgetSize.large, colors, border: border, icon: icon), Divider(color: Colors.transparent), _getRow(buttonType, ZetaWidgetSize.large, colors, isDisabled: true, border: border, icon: icon), Row( mainAxisAlignment: MainAxisAlignment.center, - children: [Padding(padding: EdgeInsets.all(10), child: Text('Medium $label', style: ZetaTextStyles.titleLarge))], + children: [Padding(padding: EdgeInsets.all(10), child: Text('Medium $label'))], ), _getRow(buttonType, ZetaWidgetSize.medium, colors, border: border, icon: icon), _getRow(buttonType, ZetaWidgetSize.medium, colors, isDisabled: true, border: border, icon: icon), Row( mainAxisAlignment: MainAxisAlignment.center, - children: [Padding(padding: EdgeInsets.all(10), child: Text('Small $label', style: ZetaTextStyles.titleLarge))], + children: [Padding(padding: EdgeInsets.all(10), child: Text('Small $label'))], ), _getRow(buttonType, ZetaWidgetSize.small, colors, border: border, icon: icon), _getRow(buttonType, ZetaWidgetSize.small, colors, isDisabled: true, border: border, icon: icon), @@ -111,7 +250,6 @@ Widget _getRow(ZetaButtonType type, ZetaWidgetSize size, ZetaButtonColors colors Widget _getZetaButtonExample(ZetaButtonType buttonType, ZetaWidgetSize size, ZetaButtonColors colors, {BorderType border = BorderType.rounded, IconData? icon, bool iconRight = false, bool isDisabled = false}) { - print(buttonType); if (buttonType == ZetaButtonType.filled) return ZetaButton.filled( label: 'Button', diff --git a/example/lib/pages/checkbox_example.dart b/example/lib/pages/components/checkbox_example.dart similarity index 84% rename from example/lib/pages/checkbox_example.dart rename to example/lib/pages/components/checkbox_example.dart index a5c93cdd..d274ca75 100644 --- a/example/lib/pages/checkbox_example.dart +++ b/example/lib/pages/components/checkbox_example.dart @@ -1,8 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../widgets.dart'; - class CheckBoxExample extends StatefulWidget { static const String name = 'Checkbox'; @@ -36,13 +35,13 @@ class _CheckBoxExampleState extends State { ) ], ), - Row(children: [Text('Sharp Checkbox Enabled', style: ZetaTextStyles.titleLarge)]), + Row(children: [Text('Sharp Checkbox Enabled')]), getCheckBoxRow(isEnabled: true), - Row(children: [Text('Sharp Checkbox Disabled', style: ZetaTextStyles.titleLarge)]), + Row(children: [Text('Sharp Checkbox Disabled')]), getCheckBoxRow(isEnabled: false), - Row(children: [Text('Rounded Checkbox Enabled', style: ZetaTextStyles.titleLarge)]), + Row(children: [Text('Rounded Checkbox Enabled')]), getCheckBoxRow(isEnabled: true, isSharp: false), - Row(children: [Text('Rounded Checkbox Disabled', style: ZetaTextStyles.titleLarge)]), + Row(children: [Text('Rounded Checkbox Disabled')]), getCheckBoxRow(isEnabled: false, isSharp: false), ], ), diff --git a/example/lib/pages/chip_example.dart b/example/lib/pages/components/chip_example.dart similarity index 99% rename from example/lib/pages/chip_example.dart rename to example/lib/pages/components/chip_example.dart index a2ad8c21..1d020481 100644 --- a/example/lib/pages/chip_example.dart +++ b/example/lib/pages/components/chip_example.dart @@ -1,8 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../widgets.dart'; - class ChipExample extends StatelessWidget { static const String name = 'Chip'; diff --git a/example/lib/pages/password_input_example.dart b/example/lib/pages/components/password_input_example.dart similarity index 98% rename from example/lib/pages/password_input_example.dart rename to example/lib/pages/components/password_input_example.dart index 9ba9e9e1..b9d2f015 100644 --- a/example/lib/pages/password_input_example.dart +++ b/example/lib/pages/components/password_input_example.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../widgets.dart'; +import '../../widgets.dart'; class PasswordInputExample extends StatefulWidget { static const String name = 'PasswordInput'; diff --git a/example/lib/pages/fab_example/fab_example.dart b/example/lib/pages/fab_example/fab_example.dart deleted file mode 100644 index e3c79269..00000000 --- a/example/lib/pages/fab_example/fab_example.dart +++ /dev/null @@ -1,100 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_example/pages/fab_example/primary_fab.dart'; -import 'package:zeta_example/pages/button_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../../home.dart'; -import '../../widgets.dart'; - -class FABExample extends StatelessWidget { - static const String name = 'FAB'; - - const FABExample({super.key}); - - @override - Widget build(BuildContext context) { - final theme = Zeta.of(context); - final colors = BuildExampleButtonColors(theme: theme); - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: FABExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.m), - child: getFABExampleColumn(colors), - ), - ); - }, - ); - } -} - -Widget getFABExampleColumn(BuildExampleButtonColors colors) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ZetaButton.filled( - label: 'Primary small circle', - colors: colors.primaryColors, - onPressed: () => router.pushNamed(FabPrimarySmallCircle.name), - icon: ZetaIcons.arrow_forward_round, - iconOnRight: true, - ), - ZetaButton.filled( - label: 'Primary small rounded', - colors: colors.primaryColors, - onPressed: () => router.pushNamed(FabPrimarySmallRounded.name), - icon: ZetaIcons.arrow_forward_round, - iconOnRight: true, - ), - ZetaButton.filled( - label: 'Primary second small sharp', - colors: colors.primaryVariantColors, - onPressed: () => router.pushNamed(FabPrimarySecondSmallSharp.name), - icon: ZetaIcons.arrow_forward_round, - iconOnRight: true, - ), - ZetaButton.filled( - label: 'Primary second large circle', - colors: colors.primaryVariantColors, - onPressed: () => router.pushNamed(FabPrimarySecondLargeCircle.name), - icon: ZetaIcons.arrow_forward_round, - iconOnRight: true, - ), - ZetaButton.outlined( - label: 'Inverse large rounded', - colors: colors.outlinedSubtle, - onPressed: () => router.pushNamed(FabInverseLargeRounded.name), - icon: ZetaIcons.arrow_forward_round, - iconOnRight: true, - ), - ZetaButton.outlined( - label: 'Inverse large sharp', - colors: colors.outlinedSubtle, - onPressed: () => router.pushNamed(FabInverseLargeSharp.name), - icon: ZetaIcons.arrow_forward_round, - iconOnRight: true, - ), - ], - ); - -Widget getFABScaffold( - ZetaFabShape shape, ZetaFabSize size, ZetaFabType type, ScrollController scrollController, String name) { - return ExampleScaffold( - floatingActionButton: ZetaFAB( - buttonLabel: 'Label', - scrollController: scrollController, - onPressed: () {}, - buttonShape: shape, - buttonSize: size, - buttonType: type, - ), - name: name, - child: ListView.builder( - controller: scrollController, - itemCount: 30, - itemBuilder: (context, index) => ListTile( - title: Text('Item $index'), - ), - ), - ); -} diff --git a/example/lib/pages/fab_example/primary_fab.dart b/example/lib/pages/fab_example/primary_fab.dart deleted file mode 100644 index 7d96d06c..00000000 --- a/example/lib/pages/fab_example/primary_fab.dart +++ /dev/null @@ -1,191 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; -import 'fab_example.dart'; - -/// Small Buttons -class FabPrimarySmallCircle extends StatefulWidget { - static const String name = 'FABPrimarySmallCircle'; - - const FabPrimarySmallCircle(); - - @override - State createState() => _FabPrimarySmallCircleState(); -} - -class _FabPrimarySmallCircleState extends State { - late ScrollController _scrollController; - - @override - void initState() { - super.initState(); - _scrollController = ScrollController(); - } - - @override - void dispose() { - _scrollController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return getFABScaffold( - ZetaFabShape.circle, ZetaFabSize.small, ZetaFabType.primary, _scrollController, FabPrimarySmallCircle.name); - } -} - -class FabPrimarySmallRounded extends StatefulWidget { - static const String name = 'FABPrimarySmallRounded'; - - const FabPrimarySmallRounded(); - - @override - State createState() => _FabPrimarySmallRoundedState(); -} - -class _FabPrimarySmallRoundedState extends State { - late ScrollController _scrollController; - - @override - void initState() { - super.initState(); - _scrollController = ScrollController(); - } - - @override - void dispose() { - _scrollController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return getFABScaffold( - ZetaFabShape.rounded, ZetaFabSize.small, ZetaFabType.primary, _scrollController, FabPrimarySmallRounded.name); - } -} - -class FabPrimarySecondSmallSharp extends StatefulWidget { - static const String name = 'FABPrimarySecondSmallSharp'; - - const FabPrimarySecondSmallSharp(); - - @override - State createState() => _FabPrimarySecondSmallSharpState(); -} - -class _FabPrimarySecondSmallSharpState extends State { - late ScrollController _scrollController; - - @override - void initState() { - super.initState(); - _scrollController = ScrollController(); - } - - @override - void dispose() { - _scrollController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return getFABScaffold(ZetaFabShape.sharp, ZetaFabSize.small, ZetaFabType.primarySecond, _scrollController, - FabPrimarySecondSmallSharp.name); - } -} - -/// Large Buttons -class FabPrimarySecondLargeCircle extends StatefulWidget { - static const String name = 'FABPrimarySecondLargeCircle'; - - const FabPrimarySecondLargeCircle(); - - @override - State createState() => _FabPrimarySecondLargeCircleState(); -} - -class _FabPrimarySecondLargeCircleState extends State { - late ScrollController _scrollController; - - @override - void initState() { - super.initState(); - _scrollController = ScrollController(); - } - - @override - void dispose() { - _scrollController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return getFABScaffold(ZetaFabShape.circle, ZetaFabSize.large, ZetaFabType.primarySecond, _scrollController, - FabPrimarySecondLargeCircle.name); - } -} - -class FabInverseLargeRounded extends StatefulWidget { - static const String name = 'FABInverseLargeRounded'; - - const FabInverseLargeRounded(); - - @override - State createState() => _FabInverseLargeRoundedState(); -} - -class _FabInverseLargeRoundedState extends State { - late ScrollController _scrollController; - - @override - void initState() { - super.initState(); - _scrollController = ScrollController(); - } - - @override - void dispose() { - _scrollController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return getFABScaffold( - ZetaFabShape.rounded, ZetaFabSize.large, ZetaFabType.inverse, _scrollController, FabInverseLargeRounded.name); - } -} - -class FabInverseLargeSharp extends StatefulWidget { - static const String name = 'FABInverseLargeSharp'; - - const FabInverseLargeSharp(); - - @override - State createState() => _FabInverseLargeSharpState(); -} - -class _FabInverseLargeSharpState extends State { - late ScrollController _scrollController; - - @override - void initState() { - super.initState(); - _scrollController = ScrollController(); - } - - @override - void dispose() { - _scrollController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return getFABScaffold( - ZetaFabShape.sharp, ZetaFabSize.large, ZetaFabType.inverse, _scrollController, FabInverseLargeSharp.name); - } -} diff --git a/example/lib/pages/in_page_banner_example.dart b/example/lib/pages/in_page_banner_example.dart deleted file mode 100644 index 819e3665..00000000 --- a/example/lib/pages/in_page_banner_example.dart +++ /dev/null @@ -1,121 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class InPageBannerExample extends StatelessWidget { - static const String name = 'InPageBanner'; - - const InPageBannerExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ExampleScaffold( - name: InPageBannerExample.name, - child: SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _getTitle('Default Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.neutral), - _getTitle('Info Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.info), - _getTitle('Positive Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.positive), - _getTitle('Warning Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.warning), - _getTitle('Negative Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.negative), - _getTitle('Custom Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.custom, - customColors: ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue)), - Divider( - height: 50, - color: Colors.transparent, - ), - _getTitle('Default Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.neutral, border: BorderType.sharp), - _getTitle('Info Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.info, border: BorderType.sharp), - _getTitle('Positive Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.positive, border: BorderType.sharp), - _getTitle('Warning Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.warning, border: BorderType.sharp), - _getTitle('Negative Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.negative, border: BorderType.sharp), - _getTitle('Custom Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.custom, - border: BorderType.sharp, - customColors: ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue)), - ], - ), - ), - ), - ); - } - - Widget _getTitle(String title) => Container( - height: 50, - child: Center(child: Text(title, style: ZetaTextStyles.titleLarge)), - ); -} - -const _content = 'Lorem ipsum dolor sit amet, conse ctetur cididunt ut' - 'labore et do lore magna aliqua.'; - -ZetaInPageBanner _getExampleBanner( - WidgetSeverity severity, - BorderType type, { - String? title, - bool showCloseBtn = true, - bool showFirstButton = false, - bool showSecondButton = false, - ZetaWidgetColor? customColors, - IconData? customIcon, -}) => - ZetaInPageBanner( - content: Text(_content), - onClose: () {}, - borderType: type, - severity: severity, - showIconClose: showCloseBtn, - title: title, - firstButton: showFirstButton ? ZetaPageBannerButton(label: 'Button', onPressed: () {}) : null, - secondButton: showSecondButton ? ZetaPageBannerButton(label: 'Button', onPressed: () {}) : null, - customColors: customColors, - customIcon: customIcon); - -Column buildExampleBannerColumn(WidgetSeverity severity, - {ZetaWidgetColor? customColors, BorderType border = BorderType.rounded, IconData? customIcon}) { - const _title = 'Banner Title'; - return Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - mainAxisSize: MainAxisSize.min, - children: [ - _getExampleBanner(severity, border, - title: _title, - showFirstButton: true, - showSecondButton: true, - customColors: customColors, - customIcon: customIcon), - //Rounded (Icon + Title + Close + Buttons) - Divider(color: Colors.transparent), - _getExampleBanner(severity, border, title: _title, customColors: customColors, customIcon: customIcon), - //Rounded (Icon + Title + Close ) - Divider(color: Colors.transparent), - _getExampleBanner(severity, border, customColors: customColors, customIcon: customIcon), - //Rounded (Icon + Close) - Divider(color: Colors.transparent), - _getExampleBanner(severity, border, - showCloseBtn: false, title: _title, customColors: customColors, customIcon: customIcon), - //Rounded (Icon + Title) - Divider(color: Colors.transparent), - _getExampleBanner(severity, border, showCloseBtn: false, customColors: customColors, customIcon: customIcon), - //Rounded (Icon) - Divider(), - //Rounded (Icon + Title + Close) - ], - ); -} diff --git a/example/lib/pages/indicator_example.dart b/example/lib/pages/indicator_example.dart deleted file mode 100644 index 6a4313ab..00000000 --- a/example/lib/pages/indicator_example.dart +++ /dev/null @@ -1,176 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class IndicatorExample extends StatelessWidget { - static const String name = 'Indicator'; - - const IndicatorExample({super.key}); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: IndicatorExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), - child: Column( - children: [ - indicatorIconExample, - const SizedBox(height: 25), - indicatorNotificationExample, - ], - ), - ), - ); - }, - ); - } - - static Widget get indicatorIconExample => Column( - children: [ - Text( - 'ZetaIndicator.icon', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 15), - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Rounded', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Row( - children: [ - ZetaIndicator.icon(), - const SizedBox(width: 20), - ZetaIndicator.icon( - size: ZetaIndicatorSize.medium, - ), - const SizedBox(width: 20), - ZetaIndicator.icon( - size: ZetaIndicatorSize.small, - ), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - ZetaIndicator.icon(inverseBorder: true), - const SizedBox(width: 20), - ZetaIndicator.icon( - size: ZetaIndicatorSize.medium, - inverseBorder: true, - ), - const SizedBox(width: 20), - ZetaIndicator.icon( - size: ZetaIndicatorSize.small, - inverseBorder: true, - ), - ], - ), - ], - ), - const SizedBox(width: 50), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Sharp', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Row( - children: [ - ZetaIndicator.icon(rounded: false), - const SizedBox(width: 20), - ZetaIndicator.icon( - size: ZetaIndicatorSize.medium, - rounded: false, - ), - const SizedBox(width: 20), - ZetaIndicator.icon( - size: ZetaIndicatorSize.small, - ), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - ZetaIndicator.icon( - rounded: false, - inverseBorder: true, - ), - const SizedBox(width: 20), - ZetaIndicator.icon( - size: ZetaIndicatorSize.medium, - rounded: false, - inverseBorder: true, - ), - const SizedBox(width: 20), - ZetaIndicator.icon( - size: ZetaIndicatorSize.small, - inverseBorder: true, - ), - ], - ), - ], - ), - ], - ), - ], - ); - - static Widget get indicatorNotificationExample => Column( - children: [ - Text( - 'ZetaIndicator.notification', - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Row( - children: [ - ZetaIndicator.notification( - value: 3, - ), - const SizedBox(width: 20), - ZetaIndicator.notification( - size: ZetaIndicatorSize.medium, - value: 3, - ), - const SizedBox(width: 20), - ZetaIndicator.notification( - size: ZetaIndicatorSize.small, - value: 3, - ), - ], - ), - const SizedBox(height: 8), - Row( - children: [ - ZetaIndicator.notification( - value: 3, - inverseBorder: true, - ), - const SizedBox(width: 20), - ZetaIndicator.notification( - size: ZetaIndicatorSize.medium, - value: 3, - inverseBorder: true, - ), - const SizedBox(width: 20), - ZetaIndicator.notification( - size: ZetaIndicatorSize.small, - inverseBorder: true, - ), - ], - ), - ], - ); -} diff --git a/example/lib/pages/menu_items_example.dart b/example/lib/pages/menu_items_example.dart deleted file mode 100644 index adda489b..00000000 --- a/example/lib/pages/menu_items_example.dart +++ /dev/null @@ -1,112 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class MenuItemsExample extends StatelessWidget { - static const String name = 'MenuItems'; - - const MenuItemsExample({super.key}); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: MenuItemsExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), - child: Column( - children: [ - Text('Horizontal'), - const SizedBox(height: 20), - horizontalExample, - const SizedBox(height: 50), - Text('Vertical'), - const SizedBox(height: 20), - verticalExample, - ], - ), - ), - ); - }, - ); - } - - static Widget get horizontalExample => Column( - children: [ - ZetaMenuItem.horizontal( - label: Text('Menu Item'), - onTap: () {}, - ), - ZetaMenuItem.horizontal( - label: Text('Menu Item'), - leadingIcon: Icon(ZetaIcons.star_round), - onTap: () {}, - ), - ZetaMenuItem.horizontal( - label: Text('Menu Item'), - showTrailing: true, - onTap: () {}, - ), - ZetaMenuItem.horizontal( - label: Text('Menu Item'), - trailingIcon: Icon(Icons.fast_forward), - onTap: () {}, - ), - ZetaMenuItem.horizontal( - label: Text('Menu Item'), - leadingIcon: Icon(ZetaIcons.phone_android_round), - showTrailing: true, - onTap: () {}, - ), - ZetaMenuItem.horizontal( - label: Text('Disabled Menu Item'), - leadingIcon: Icon(ZetaIcons.home_round), - showTrailing: true, - disabled: true, - onTap: () {}, - ), - ], - ); - - static Widget get verticalExample => Wrap( - spacing: 16, - runSpacing: 16, - children: [ - ZetaMenuItem.vertical( - label: Text('Menu Item'), - icon: Icon(ZetaIcons.star_round), - onTap: () {}, - ), - ZetaMenuItem.vertical( - label: Text('Menu Item'), - icon: Icon(ZetaIcons.star_sharp), - onTap: () {}, - ), - ZetaMenuItem.vertical( - label: Text('Menu Item'), - icon: Icon(ZetaIcons.home_round), - onTap: () {}, - ), - ZetaMenuItem.vertical( - label: Text('Menu Item'), - icon: Icon(ZetaIcons.star_round), - onTap: () {}, - disabled: true, - ), - ZetaMenuItem.vertical( - label: Text('Menu Item'), - icon: Icon(ZetaIcons.star_sharp), - onTap: () {}, - disabled: true, - ), - ZetaMenuItem.vertical( - label: Text('Menu Item'), - icon: Icon(ZetaIcons.home_round), - onTap: () {}, - disabled: true, - ), - ], - ); -} diff --git a/example/lib/pages/priority_pill_example.dart b/example/lib/pages/priority_pill_example.dart deleted file mode 100644 index 29f47a6a..00000000 --- a/example/lib/pages/priority_pill_example.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class PriorityPillExample extends StatelessWidget { - static const String name = 'PriorityPill'; - - const PriorityPillExample(); - - @override - Widget build(BuildContext context) { - return ExampleScaffold( - name: 'PriorityPill', - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ZetaPriorityPill( - index: 1, - priority: 'Rounded', - borderType: BorderType.rounded, - ), - ZetaPriorityPill( - index: 2, - priority: 'Sharp', - ) - ], - ), - ), - ); - } -} diff --git a/example/lib/pages/status_label_example.dart b/example/lib/pages/status_label_example.dart deleted file mode 100644 index fa4d384a..00000000 --- a/example/lib/pages/status_label_example.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class LabelExample extends StatelessWidget { - static const String name = 'StatusLabel'; - - const LabelExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ExampleScaffold( - name: LabelExample.name, - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - statusLabelExampleRow(WidgetSeverity.neutral), - statusLabelExampleRow(WidgetSeverity.info), - statusLabelExampleRow(WidgetSeverity.positive), - statusLabelExampleRow(WidgetSeverity.warning), - statusLabelExampleRow(WidgetSeverity.negative), - statusLabelExampleRow( - WidgetSeverity.custom, - colors: ZetaWidgetColor(foregroundColor: Colors.blue, backgroundColor: Colors.blue.shade50), - ), - ], - ), - ), - ); - } -} - -Widget statusLabelExampleRow(WidgetSeverity type, {ZetaWidgetColor? colors}) { - return Padding( - padding: EdgeInsets.all(10), - child: - Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ - ZetaStatusLabel( - label: 'Label', - severity: type, - isDefaultIcon: false, - customColors: colors, - ), - ZetaStatusLabel( - label: 'Label', - severity: type, - borderType: BorderType.rounded, - customColors: colors, - ), - ]), - ); -} diff --git a/example/lib/pages/tag_example.dart b/example/lib/pages/tag_example.dart deleted file mode 100644 index f24bdb60..00000000 --- a/example/lib/pages/tag_example.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class TagExample extends StatelessWidget { - static const String name = 'Tag'; - - const TagExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ExampleScaffold( - name: TagExample.name, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [tagsRowLeft, tagsRowRight], - ), - ); - } - - static Widget get tagsRowLeft => Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ZetaTag.left( - label: 'Tag', - borderType: BorderType.sharp, - ), - ZetaTag.left( - label: 'Tag', - borderType: BorderType.rounded, - ) - ], - ); - - static Widget get tagsRowRight => Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ZetaTag.right( - label: 'Tag', - borderType: BorderType.sharp, - ), - ZetaTag.right( - label: 'Tag', - borderType: BorderType.rounded, - ) - ], - ); -} diff --git a/example/lib/pages/color_example.dart b/example/lib/pages/theme/color_example.dart similarity index 99% rename from example/lib/pages/color_example.dart rename to example/lib/pages/theme/color_example.dart index 23b6fe6c..eeb0d4aa 100644 --- a/example/lib/pages/color_example.dart +++ b/example/lib/pages/theme/color_example.dart @@ -1,8 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../widgets.dart'; - class ColorExample extends StatefulWidget { static const String name = 'Color'; diff --git a/example/lib/pages/workcloud_indicator_example.dart b/example/lib/pages/workcloud_indicator_example.dart deleted file mode 100644 index 95a6259e..00000000 --- a/example/lib/pages/workcloud_indicator_example.dart +++ /dev/null @@ -1,99 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../widgets.dart'; - -class WorkcloudIndicatorExample extends StatelessWidget { - static const String name = 'WorkcloudIndicator'; - - const WorkcloudIndicatorExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ExampleScaffold( - name: WorkcloudIndicatorExample.name, - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisSize: MainAxisSize.min, - children: [ - ZetaWorkcloudIndicator( - label: 'Test Status Badge', - ), - ], - ), - SizedBox(height: 10), - Row(children: [ZetaWorkcloudIndicator.status(label: 'Status')]), - SizedBox(height: 10), - Row(children: [ZetaWorkcloudIndicator.status(label: 'In Progress')]), - SizedBox(height: 10), - Row(children: [ZetaWorkcloudIndicator.status(label: 'Reviewed')]), - SizedBox(height: 10), - Row(children: [ZetaWorkcloudIndicator.status(label: 'Resolved')]), - SizedBox(height: 100), - Padding( - padding: EdgeInsets.all(10), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [Text('Medium'), Text('Small'), Text('X-Small')], - ), - ), - workcloudIndicatorExampleRow('Urgent', 'U', ZetaWorkcloudIndicatorType.urgent), - SizedBox(height: 10), - workcloudIndicatorExampleRow('High', '1', ZetaWorkcloudIndicatorType.high), - SizedBox(height: 10), - workcloudIndicatorExampleRow('Medium', '2', ZetaWorkcloudIndicatorType.medium), - SizedBox(height: 10), - workcloudIndicatorExampleRow('Low', '3', ZetaWorkcloudIndicatorType.low), - SizedBox(height: 10), - workcloudIndicatorExampleRow('Custom', '4', ZetaWorkcloudIndicatorType.custom, - colors: ZetaWidgetColor(backgroundColor: Colors.purple, foregroundColor: Colors.purple.shade50)), - ], - ), - ), - ); - } -} - -List workcloudIndicatorStatusRow(String label) { - return [ - Row(children: [ZetaWorkcloudIndicator.status(label: label)]), - SizedBox(height: 10) - ]; -} - -Widget workcloudIndicatorExampleRow(String label, String index, ZetaWorkcloudIndicatorType type, - {ZetaWidgetColor? colors}) { - return Padding( - padding: EdgeInsets.all(10), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ZetaWorkcloudIndicator.priorityPill( - index: index, - label: label, - priorityType: type, - prioritySize: ZetaWidgetSize.large, - customColors: colors, - ), - ZetaWorkcloudIndicator.priorityPill( - index: index, - label: label, - prioritySize: ZetaWidgetSize.medium, - priorityType: type, - customColors: colors, - ), - ZetaWorkcloudIndicator.priorityPill( - index: index, - label: label, - priorityType: type, - customColors: colors, - ), - ], - ), - ); -} diff --git a/example/lib/theme_service.dart b/example/lib/theme_service.dart index b25c0a45..3c80a1b9 100644 --- a/example/lib/theme_service.dart +++ b/example/lib/theme_service.dart @@ -1,6 +1,6 @@ import 'package:flutter/src/material/app.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:zeta_example/pages/theme_color_switch.dart'; +import 'package:zeta_example/utils/theme_color_switch.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; class SharedPrefsThemeService extends ZetaThemeService { diff --git a/example/lib/pages/theme_color_switch.dart b/example/lib/utils/theme_color_switch.dart similarity index 100% rename from example/lib/pages/theme_color_switch.dart rename to example/lib/utils/theme_color_switch.dart diff --git a/example/lib/pages/theme_constrast_switch.dart b/example/lib/utils/theme_constrast_switch.dart similarity index 100% rename from example/lib/pages/theme_constrast_switch.dart rename to example/lib/utils/theme_constrast_switch.dart diff --git a/example/lib/pages/theme_mode_switch.dart b/example/lib/utils/theme_mode_switch.dart similarity index 100% rename from example/lib/pages/theme_mode_switch.dart rename to example/lib/utils/theme_mode_switch.dart diff --git a/example/lib/widgets.dart b/example/lib/widgets.dart index 9cc7199b..27993c41 100644 --- a/example/lib/widgets.dart +++ b/example/lib/widgets.dart @@ -1,9 +1,8 @@ import 'package:flutter/material.dart'; - import 'package:google_fonts/google_fonts.dart'; -import 'package:zeta_example/pages/theme_color_switch.dart'; -import 'package:zeta_example/pages/theme_constrast_switch.dart'; -import 'package:zeta_example/pages/theme_mode_switch.dart'; +import 'package:zeta_example/utils/theme_color_switch.dart'; +import 'package:zeta_example/utils/theme_constrast_switch.dart'; +import 'package:zeta_example/utils/theme_mode_switch.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; class ExampleModel { diff --git a/example/pubspec.lock b/example/pubspec.lock index a60f4020..ed710c29 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+21" + version: "0.1.1+22" sdks: dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" diff --git a/example/widgetbook/components/button_widgetbook.dart b/example/widgetbook/components/button_widgetbook.dart index 4166d90d..104e0827 100644 --- a/example/widgetbook/components/button_widgetbook.dart +++ b/example/widgetbook/components/button_widgetbook.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/button_example.dart'; +import 'package:zeta_example/pages/components/button_example.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; import '../../test/test_components.dart'; diff --git a/example/widgetbook/theme/color_widgetbook.dart b/example/widgetbook/theme/color_widgetbook.dart index dc0b1298..247298bd 100644 --- a/example/widgetbook/theme/color_widgetbook.dart +++ b/example/widgetbook/theme/color_widgetbook.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/color_example.dart'; +import 'package:zeta_example/pages/theme/color_example.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; WidgetbookComponent colorWidgetBook() { diff --git a/pubspec.yaml b/pubspec.yaml index e47fba44..a2d399a5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: zeta_flutter -version: 0.1.1+22 +version: 0.1.1+23 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. From 074fe3d9e759da1aee7e3f1fba6dee79d28062b1 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Mon, 29 Jan 2024 10:54:53 +0000 Subject: [PATCH 33/41] chore: Update Github action (#54) https://jira.zebra.com/browse/UX-913 --- .firebaserc | 5 + .github/workflows/on-release.yml | 20 ++++ .github/workflows/onMerge.yml | 113 ------------------ .../workflows/{pr.yml => pull-request.yml} | 67 ++++++++--- .github/workflows/release-please.yml | 17 +++ firebase.json | 11 ++ 6 files changed, 103 insertions(+), 130 deletions(-) create mode 100644 .firebaserc create mode 100644 .github/workflows/on-release.yml delete mode 100644 .github/workflows/onMerge.yml rename .github/workflows/{pr.yml => pull-request.yml} (60%) create mode 100644 .github/workflows/release-please.yml create mode 100644 firebase.json diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 00000000..91581093 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "zeta-ds" + } +} \ No newline at end of file diff --git a/.github/workflows/on-release.yml b/.github/workflows/on-release.yml new file mode 100644 index 00000000..fda831d4 --- /dev/null +++ b/.github/workflows/on-release.yml @@ -0,0 +1,20 @@ +name: "CI - Release" +on: + workflow_dispatch: + release: + types: [released] + +jobs: + deploy-website: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v6 + with: + github-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + script: | + await github.rest.actions.createworkflowDispatch({ + owner: 'zebratechnologies', + repo: 'zeta', + workflow_id: 'deploy-prod.yml', + ref: 'main' + }) diff --git a/.github/workflows/onMerge.yml b/.github/workflows/onMerge.yml deleted file mode 100644 index eff5b98a..00000000 --- a/.github/workflows/onMerge.yml +++ /dev/null @@ -1,113 +0,0 @@ -name: "Merge" - -on: - pull_request: - types: [closed] - -jobs: - changes: - if: github.event.pull_request.merged - runs-on: ubuntu-latest - timeout-minutes: 5 - outputs: - files: ${{steps.changed-files.outputs.any_changed}} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: main - persist-credentials: false - - name: Get all changed *.dart, files in docs or pubspec.yaml - id: changed-files - uses: tj-actions/changed-files@v41 - with: - files: | - **/*.dart - custom-docs/* - **/*.yaml - **/*.yml - files_ignore: example/* - update-version: - runs-on: ubuntu-latest - timeout-minutes: 5 - needs: changes - if: needs.changes.outputs.files == 'true' - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: main - persist-credentials: false - - name: Run step if any *.js file(s) or any file in the static folder change - if: steps.changed-files-excluded.outputs.any_changed == 'true' - run: | - echo "One or more *.js file(s) or any file in the static folder but not in the custom-docs folder has changed." - echo "List all the files that have changed: ${{ steps.changed-files-excluded.outputs.all_changed_files }}" - - name: Change flutter version tag - uses: BentEngbers/flutter-change-version@v1.0.3 - - name: push change - id: update - run: | - git remote set-url origin https://${{ secrets.PERSONAL_ACCESS_TOKEN}}@github.com/zebratechnologies/zeta-flutter.git - git config --global user.name "github-actions" - git config --global user.email "github-actions@github.com" - git add -A - git commit --amend --no-edit - git push -f - publish-changelog: - needs: [changes, update-version] - if: needs.changes.outputs.files == 'true' - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v3 - with: - ref: main - fetch-depth: 0 - persist-credentials: false - - id: read-version - uses: NiklasLehnfeld/flutter-version-number-action@main - - name: Create tag - uses: actions/github-script@v5 - with: - script: | - github.rest.git.createRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: 'refs/tags/${{steps.read-version.outputs.version-number}}', - sha: "${{github.sha}}" - }) - - name: Update CHANGELOG - id: changelog - uses: requarks/changelog-action@v1 - with: - token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - tag: ${{ steps.read-version.outputs.version-number }} - excludeTypes: "" - includeInvalidCommits: true - - name: Check for modified files - id: git-check - run: echo "modified=$(if [ -n "$(git status --porcelain)" ]; then echo "true"; else echo "false"; fi)" >> $GITHUB_ENV - - name: Update changes in zeta-flutter repository - if: env.modified == 'true' - run: | - git remote set-url origin https://${{ secrets.PERSONAL_ACCESS_TOKEN}}@github.com/zebratechnologies/zeta-flutter.git - git config --global user.name "github-actions" - git config --global user.email "github-actions@github.com" - git add -A - git commit --amend --no-edit - git push -f - - name: Make changelog flutter - run: cp CHANGELOG.md CHANGELOG_FLUTTER.md - - name: Push changelog to Zeta - uses: dmnemec/copy_file_to_another_repo_action@main - env: - API_TOKEN_GITHUB: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - with: - source_file: "CHANGELOG_FLUTTER.md" - destination_repo: "zebratechnologies/zeta" - destination_folder: "./" - destination_branch_create: "flutter/${{ steps.read-version.outputs.version-number }}" - user_email: "github-actions@github.com" - user_name: "github-actions" - commit_message: "flutter changelog" diff --git a/.github/workflows/pr.yml b/.github/workflows/pull-request.yml similarity index 60% rename from .github/workflows/pr.yml rename to .github/workflows/pull-request.yml index 244a6311..df90b783 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pull-request.yml @@ -1,15 +1,35 @@ -name: "PR" -on: - pull_request: +name: CI - Pull Request +on: pull_request jobs: + up-to-date: + name: "Check branch is up to date" + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.head_ref }} + - name: Check branch is up to date + run: | + if git merge-base --is-ancestor ${{ github.event.pull_request.base.sha}} ${{ github.event.pull_request.head.sha}} + then + echo "Your branch is up to date." + exit 0 + else + echo "You need to merge / rebase." + exit 1 + fi changes: + name: "Check for changes in code" + needs: up-to-date runs-on: ubuntu-latest timeout-minutes: 5 outputs: files: ${{steps.changed-files.outputs.any_changed}} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 ref: main @@ -24,32 +44,22 @@ jobs: **/*.dart custom-docs pubspec.yaml - analyze: + code-quality: runs-on: ubuntu-latest timeout-minutes: 20 needs: changes if: needs.changes.outputs.files == 'true' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.head_ref }} - - name: Check branch is up to date - run: | - if git merge-base --is-ancestor ${{ github.event.pull_request.base.sha}} ${{ github.event.pull_request.head.sha}} - then - echo "Your branch is up to date." - exit 0 - else - echo "You need to merge / rebase." - exit 1 - fi - name: Get branch name id: branch-name uses: tj-actions/branch-names@v7.0.7 - uses: subosito/flutter-action@v2 with: - flutter-version: "3.13.x" + flutter-version: "3.16.x" channel: "stable" - name: Setup flutter run: flutter pub get @@ -70,3 +80,26 @@ jobs: git add -A git commit -m '[automated commit] lint format and import sort' git push + deploy-preview: + name: Deploy preview version of the storybook on firebase + needs: code-quality + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: subosito/flutter-action@v2 + with: + flutter-version: "3.16.x" + channel: "stable" + - name: Setup flutter + run: flutter pub get + - name: Build example app + run: | + cd example + flutter build web -o ../build --no-tree-shake-icons + - uses: FirebaseExtended/action-hosting-deploy@v0 + with: + repoToken: "${{ secrets.GITHUB_TOKEN }}" + firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_ZETA_DS }}" + expires: 7d + projectId: zeta-ds + channelId: "pr-${{ github.event.number }}-${{ github.event.pull_request.head.ref }}" diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 00000000..197446e0 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,17 @@ +name: release-please +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: google-github-actions/release-please-action@v4 + with: + token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} diff --git a/firebase.json b/firebase.json new file mode 100644 index 00000000..4a130f50 --- /dev/null +++ b/firebase.json @@ -0,0 +1,11 @@ +{ + "hosting": { + "public": "build", + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ] + } +} \ No newline at end of file From cb6b4bdd62f3bca2d47178585bbf263e314e8031 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Mon, 29 Jan 2024 15:45:49 +0000 Subject: [PATCH 34/41] chore: Refactor components part 1 (#55) https://jira.zebra.com/browse/UX-918 Part 1 of 2 due to size. - [x] Accordion - [ ] Avatar - [x] Badges - [x] Banner - [ ] Bottom Sheet - [x] Button - [ ] Checkbox - [ ] Chip - [ ] Password Input --- example/lib/pages/assets/icons_example.dart | 2 +- .../pages/components/accordion_example.dart | 2 +- .../lib/pages/components/avatar_example.dart | 4 +- .../lib/pages/components/badges_example.dart | 159 +++----- .../lib/pages/components/banner_example.dart | 252 ++++++------ .../lib/pages/components/bottom_sheet.dart | 2 +- .../lib/pages/components/button_example.dart | 203 ++-------- .../lib/pages/components/chip_example.dart | 2 +- .../components/password_input_example.dart | 6 +- example/lib/pages/theme/color_example.dart | 10 +- .../lib/pages/theme/typography_example.dart | 2 +- example/lib/widgets.dart | 9 +- example/pubspec.lock | 28 +- example/test/badge_test.dart | 6 +- example/test/button_test.dart | 16 +- example/test/in_page_banner_test.dart | 18 +- example/test/status_label_test.dart | 1 - example/test/workcloud_indicator_test.dart | 29 +- .../components/accordion_widgetbook.dart | 2 +- .../components/badges_widgetbook.dart | 46 ++- .../components/banner_widgetbook.dart | 54 ++- .../components/button_widgetbook.dart | 44 --- .../components/password_input_widgetbook.dart | 2 +- .../widgetbook/theme/color_widgetbook.dart | 8 +- .../theme/typography_widgetbook.dart | 2 +- lib/src/components/accordion/accordion.dart | 67 ++-- lib/src/components/avatars/avatar.dart | 15 +- lib/src/components/badges/badge.dart | 118 ++---- lib/src/components/badges/indicator.dart | 196 +++------- lib/src/components/badges/priority_pill.dart | 86 ++--- lib/src/components/badges/status_label.dart | 157 ++------ lib/src/components/badges/tag.dart | 187 ++++----- .../badges/workcloud_indicator.dart | 319 +++++---------- .../components/banners/in_page_banner.dart | 291 +++++--------- lib/src/components/banners/system_banner.dart | 222 ++++------- lib/src/components/buttons/button.dart | 365 ++++++++++-------- lib/src/components/buttons/fab.dart | 12 +- lib/src/components/checkbox/checkbox.dart | 4 +- lib/src/components/chip/chip.dart | 2 +- .../components/password/password_input.dart | 26 +- lib/src/theme/colors.dart | 10 +- lib/src/theme/tokens.dart | 22 +- lib/src/utils/enums.dart | 26 +- lib/src/utils/extensions.dart | 33 ++ release-please-config.json | 7 + 45 files changed, 1221 insertions(+), 1853 deletions(-) create mode 100644 release-please-config.json diff --git a/example/lib/pages/assets/icons_example.dart b/example/lib/pages/assets/icons_example.dart index 182a2430..079558cc 100644 --- a/example/lib/pages/assets/icons_example.dart +++ b/example/lib/pages/assets/icons_example.dart @@ -22,7 +22,7 @@ class _IconsExampleState extends State { return ExampleScaffold( name: IconsExample.name, child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), + padding: EdgeInsets.all(ZetaSpacing.s), child: Column( children: [ Text('Round', style: ZetaTextStyles.bodyLarge), diff --git a/example/lib/pages/components/accordion_example.dart b/example/lib/pages/components/accordion_example.dart index 0c52a2c2..7887683a 100644 --- a/example/lib/pages/components/accordion_example.dart +++ b/example/lib/pages/components/accordion_example.dart @@ -14,7 +14,7 @@ class AccordionExample extends StatelessWidget { return ExampleScaffold( name: AccordionExample.name, child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), + padding: EdgeInsets.all(ZetaSpacing.s), child: Column( children: [ Text('Rounded Divider'), diff --git a/example/lib/pages/components/avatar_example.dart b/example/lib/pages/components/avatar_example.dart index a8b3a3b3..7b210148 100644 --- a/example/lib/pages/components/avatar_example.dart +++ b/example/lib/pages/components/avatar_example.dart @@ -14,7 +14,7 @@ class AvatarExample extends StatelessWidget { return ExampleScaffold( name: AvatarExample.name, child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), + padding: EdgeInsets.all(ZetaSpacing.s), child: Column( children: [ Column( @@ -498,7 +498,7 @@ class AvatarExample extends StatelessWidget { ), ], ), - ].divide(const SizedBox(height: Dimensions.x6)).toList(), + ].divide(const SizedBox(height: ZetaSpacing.x6)).toList(), ), ), ); diff --git a/example/lib/pages/components/badges_example.dart b/example/lib/pages/components/badges_example.dart index b7fe49ab..919e3a44 100644 --- a/example/lib/pages/components/badges_example.dart +++ b/example/lib/pages/components/badges_example.dart @@ -44,20 +44,20 @@ class _DividingText extends StatelessWidget { return Text( text, style: ZetaTextStyles.displayMedium, - ).paddingVertical(Dimensions.l); + ).paddingVertical(ZetaSpacing.l); } } class _StatusLabel extends StatelessWidget { const _StatusLabel(); - Widget statusLabelExampleRow(WidgetSeverity type, {ZetaWidgetColor? colors}) { + Widget statusLabelExampleRow(ZetaWidgetStatus type, {ZetaWidgetColor? colors}) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ - ZetaStatusLabel(label: 'Label', severity: type, isDefaultIcon: false, customColors: colors), - ZetaStatusLabel(label: 'Label', severity: type, borderType: BorderType.rounded, customColors: colors), + ZetaStatusLabel(label: 'Label', status: type, rounded: false), + ZetaStatusLabel(label: 'Label', status: type, rounded: true), ], ); } @@ -66,16 +66,12 @@ class _StatusLabel extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ - statusLabelExampleRow(WidgetSeverity.neutral), - statusLabelExampleRow(WidgetSeverity.info), - statusLabelExampleRow(WidgetSeverity.positive), - statusLabelExampleRow(WidgetSeverity.warning), - statusLabelExampleRow(WidgetSeverity.negative), - statusLabelExampleRow( - WidgetSeverity.custom, - colors: ZetaWidgetColor(foregroundColor: Colors.blue, backgroundColor: Colors.blue.shade50), - ) - ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + statusLabelExampleRow(ZetaWidgetStatus.neutral), + statusLabelExampleRow(ZetaWidgetStatus.info), + statusLabelExampleRow(ZetaWidgetStatus.positive), + statusLabelExampleRow(ZetaWidgetStatus.warning), + statusLabelExampleRow(ZetaWidgetStatus.negative), + ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ); } } @@ -88,9 +84,9 @@ class _PriorityPill extends StatelessWidget { return Row( mainAxisSize: MainAxisSize.min, children: [ - ZetaPriorityPill(index: 1, priority: 'Rounded', borderType: BorderType.rounded), - ZetaPriorityPill(index: 2, priority: 'Sharp'), - ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ZetaPriorityPill(index: 1000, priority: 'Rounded', rounded: true), + ZetaPriorityPill(index: 2, priority: 'Sharp', rounded: false), + ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ); } } @@ -98,13 +94,13 @@ class _PriorityPill extends StatelessWidget { class _Badge extends StatelessWidget { const _Badge(); - Widget badgeExampleRow(WidgetSeverity type) { + Widget badgeExampleRow(ZetaWidgetStatus type) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ - ZetaBadge(label: 'Label', severity: type, borderType: BorderType.sharp), - ZetaBadge(label: 'Label', severity: type), + ZetaBadge(label: 'Label', status: type, rounded: false), + ZetaBadge(label: 'Label', status: type), ], ); } @@ -113,12 +109,12 @@ class _Badge extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ - badgeExampleRow(WidgetSeverity.info), - badgeExampleRow(WidgetSeverity.positive), - badgeExampleRow(WidgetSeverity.warning), - badgeExampleRow(WidgetSeverity.negative), - badgeExampleRow(WidgetSeverity.neutral), - ].divide(const SizedBox(height: Dimensions.m)).toList(), + badgeExampleRow(ZetaWidgetStatus.info), + badgeExampleRow(ZetaWidgetStatus.positive), + badgeExampleRow(ZetaWidgetStatus.warning), + badgeExampleRow(ZetaWidgetStatus.negative), + badgeExampleRow(ZetaWidgetStatus.neutral), + ].divide(const SizedBox(height: ZetaSpacing.m)).toList(), ); } } @@ -149,44 +145,23 @@ class _Indicators extends StatelessWidget { ZetaIndicator.icon(), ZetaIndicator.icon(size: ZetaIndicatorSize.medium), ZetaIndicator.icon(size: ZetaIndicatorSize.small), - ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ), Row( children: [ ZetaIndicator.icon(inverseBorder: true), ZetaIndicator.icon(size: ZetaIndicatorSize.medium, inverseBorder: true), ZetaIndicator.icon(size: ZetaIndicatorSize.small, inverseBorder: true), - ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ), - Text('Rounded', style: TextStyle(fontWeight: FontWeight.bold)), - ].divide(const SizedBox.square(dimension: Dimensions.xs)).toList(), + ].divide(const SizedBox.square(dimension: ZetaSpacing.xs)).toList(), ), const SizedBox(width: 50), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - ZetaIndicator.icon(rounded: false), - ZetaIndicator.icon(size: ZetaIndicatorSize.medium, rounded: false), - ZetaIndicator.icon(size: ZetaIndicatorSize.small), - ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), - ), - Row( - children: [ - ZetaIndicator.icon(rounded: false, inverseBorder: true), - ZetaIndicator.icon(size: ZetaIndicatorSize.medium, rounded: false, inverseBorder: true), - ZetaIndicator.icon(size: ZetaIndicatorSize.small, inverseBorder: true), - ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), - ), - Text('Sharp', style: TextStyle(fontWeight: FontWeight.bold)), - ].divide(const SizedBox.square(dimension: Dimensions.s)).toList(), - ), ], ), ], ), - const SizedBox.square(dimension: Dimensions.xl), + const SizedBox.square(dimension: ZetaSpacing.xl), Column( children: [ Text('ZetaIndicator.notification', style: TextStyle(fontWeight: FontWeight.bold)), @@ -202,17 +177,16 @@ class _Indicators extends StatelessWidget { ZetaIndicator.notification(value: 3), ZetaIndicator.notification(size: ZetaIndicatorSize.medium, value: 3), ZetaIndicator.notification(size: ZetaIndicatorSize.small), - ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ), Row( children: [ ZetaIndicator.notification(value: 3, inverseBorder: true), ZetaIndicator.notification(size: ZetaIndicatorSize.medium, value: 3, inverseBorder: true), ZetaIndicator.notification(size: ZetaIndicatorSize.small, inverseBorder: true), - ].divide(const SizedBox.square(dimension: Dimensions.m)).toList(), + ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ), - Text('', style: TextStyle(fontWeight: FontWeight.bold)), - ].divide(const SizedBox.square(dimension: Dimensions.s)).toList(), + ].divide(const SizedBox.square(dimension: ZetaSpacing.s)).toList(), ), ], ), @@ -228,14 +202,17 @@ class _Tags extends StatelessWidget { @override Widget build(BuildContext context) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - ZetaTag.left(label: 'Sharp', borderType: BorderType.sharp), - ZetaTag.right(label: 'Sharp', borderType: BorderType.sharp), - ZetaTag.left(label: 'Rounded', borderType: BorderType.sharp), - ZetaTag.right(label: 'Rounded', borderType: BorderType.rounded), - ].divide(SizedBox.square(dimension: Dimensions.m)).toList(), + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + ZetaTag.left(label: 'Sharp', rounded: false), + ZetaTag.right(label: 'Sharp', rounded: false), + ZetaTag.left(label: 'Rounded'), + ZetaTag.right(label: 'Rounded'), + ].divide(SizedBox.square(dimension: ZetaSpacing.m)).toList(), + ), ); } } @@ -243,28 +220,25 @@ class _Tags extends StatelessWidget { class _WorkcloudIndicators extends StatelessWidget { const _WorkcloudIndicators(); - List workcloudIndicatorStatusRow(String label) { - return [ - Row(children: [ZetaWorkcloudIndicator.status(label: label)]), - SizedBox(height: 10) - ]; - } - - Widget workcloudIndicatorExampleRow(String label, String index, ZetaWorkcloudIndicatorType type, - {ZetaWidgetColor? colors}) { + Widget workcloudIndicatorExampleRow(ZetaWorkcloudIndicatorType type) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ZetaWorkcloudIndicator.priorityPill( - index: index, label: label, priorityType: type, prioritySize: ZetaWidgetSize.large, customColors: colors), - ZetaWorkcloudIndicator.priorityPill( - index: index, - label: label, + ZetaWorkcloudIndicator( + priorityType: type, + prioritySize: ZetaWidgetSize.large, + icon: ZetaIcons.star_half_round, + label: 'Label', + ), + ZetaWorkcloudIndicator( prioritySize: ZetaWidgetSize.medium, + index: '14', + priorityType: type, + label: 'Label!', + ), + ZetaWorkcloudIndicator( priorityType: type, - customColors: colors, ), - ZetaWorkcloudIndicator.priorityPill(index: index, label: label, priorityType: type, customColors: colors), ], ); } @@ -273,16 +247,6 @@ class _WorkcloudIndicators extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ - Row( - mainAxisSize: MainAxisSize.min, - children: [ - ZetaWorkcloudIndicator(label: 'Test Status Badge'), - ZetaWorkcloudIndicator.status(label: 'Status'), - ZetaWorkcloudIndicator.status(label: 'In Progress'), - ZetaWorkcloudIndicator.status(label: 'Reviewed'), - ZetaWorkcloudIndicator.status(label: 'Resolved') - ].divide(const SizedBox.square(dimension: Dimensions.s)).toList(), - ), SizedBox(height: 30), Column( children: [ @@ -290,18 +254,11 @@ class _WorkcloudIndicators extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text('Medium'), Text('Small'), Text('X-Small')], ), - workcloudIndicatorExampleRow('Urgent', 'U', ZetaWorkcloudIndicatorType.urgent), - workcloudIndicatorExampleRow('High', '1', ZetaWorkcloudIndicatorType.high), - workcloudIndicatorExampleRow('Medium', '2', ZetaWorkcloudIndicatorType.medium), - workcloudIndicatorExampleRow('Low', '3', ZetaWorkcloudIndicatorType.low), - workcloudIndicatorExampleRow( - 'Custom', - '4', - ZetaWorkcloudIndicatorType.custom, - colors: ZetaWidgetColor(backgroundColor: Colors.purple, foregroundColor: Colors.purple.shade50), - ), - ].divide(const SizedBox.square(dimension: Dimensions.s)).toList(), - ).paddingAll(Dimensions.m) + ...List.generate(10, (index) { + return workcloudIndicatorExampleRow(ZetaWorkcloudIndicatorType.values[index]); + }), + ].divide(const SizedBox.square(dimension: ZetaSpacing.s)).toList(), + ).paddingAll(ZetaSpacing.m) ], ); } diff --git a/example/lib/pages/components/banner_example.dart b/example/lib/pages/components/banner_example.dart index 02e35209..3a838897 100644 --- a/example/lib/pages/components/banner_example.dart +++ b/example/lib/pages/components/banner_example.dart @@ -20,92 +20,156 @@ class BannerExample extends StatelessWidget { Text('System Banner', style: ZetaTextStyles.displayMedium), _getTitle('Style variants'), ZetaSystemBanner( - type: ZetaSystemBannerType.defaultAppBar, - title: Text('Centered'), - centerTitle: true, - titleIcon: Icon(ZetaIcons.info_round), + type: ZetaSystemBannerStatus.primary, + title: 'Centered', + context: context, + titleStart: true, + leadingIcon: ZetaIcons.info_round, ), ZetaSystemBanner( - type: ZetaSystemBannerType.defaultAppBar, - title: Text('Title Left'), + type: ZetaSystemBannerStatus.primary, + context: context, + title: 'Title Left', ), ZetaSystemBanner( - type: ZetaSystemBannerType.defaultAppBar, - title: Text('Title left with arrow'), - centerTitle: true, - actions: [Icon(ZetaIcons.chevron_right_round)], + type: ZetaSystemBannerStatus.primary, + context: context, + title: 'Title left with arrow', + titleStart: true, + trailing: Icon(ZetaIcons.chevron_right_round), ), ZetaSystemBanner( - type: ZetaSystemBannerType.defaultAppBar, - title: Text('Title left + Icon'), - centerTitle: true, - titleIcon: Icon(ZetaIcons.info_round), + type: ZetaSystemBannerStatus.primary, + title: 'Title left + Icon', + titleStart: true, + context: context, + leadingIcon: ZetaIcons.info_round, ), ZetaSystemBanner( - type: ZetaSystemBannerType.defaultAppBar, - title: Text('Title left + Icon with Arrow'), - centerTitle: true, - titleIcon: Icon(ZetaIcons.info_round), - actions: [Icon(ZetaIcons.chevron_right_round)], + type: ZetaSystemBannerStatus.primary, + context: context, + title: 'Title left + Icon with Arrow', + titleStart: true, + leadingIcon: ZetaIcons.info_round, + trailing: IconButton( + icon: Icon(ZetaIcons.chevron_right_round), + onPressed: () { + ScaffoldMessenger.of(context).showMaterialBanner(ZetaSystemBanner( + title: 'Title', + context: context, + type: ZetaSystemBannerStatus.primary, + trailing: IconButton( + icon: Icon(ZetaIcons.close_round), + onPressed: () => ScaffoldMessenger.of(context).clearMaterialBanners(), + ), + )); + }, + ), ), _getTitle('Color variants'), ZetaSystemBanner( - type: ZetaSystemBannerType.positiveAppBar, - title: Text('Centered'), - centerTitle: true, - titleIcon: Icon(ZetaIcons.info_round), + type: ZetaSystemBannerStatus.positive, + context: context, + title: 'Centered', + titleStart: true, + leadingIcon: ZetaIcons.info_round, + trailing: IconButton( + icon: Icon(ZetaIcons.chevron_right_round), + onPressed: () { + ScaffoldMessenger.of(context).showMaterialBanner(ZetaSystemBanner( + title: 'Title', + context: context, + type: ZetaSystemBannerStatus.positive, + trailing: IconButton( + icon: Icon(ZetaIcons.close_round), + onPressed: () => ScaffoldMessenger.of(context).clearMaterialBanners(), + ), + )); + }, + ), ), ZetaSystemBanner( - type: ZetaSystemBannerType.warningAppBar, - title: Text('Centered'), - centerTitle: true, - titleIcon: Icon(ZetaIcons.info_round), + type: ZetaSystemBannerStatus.warning, + title: 'Centered', + context: context, + titleStart: true, + leadingIcon: ZetaIcons.info_round, + trailing: IconButton( + icon: Icon(ZetaIcons.chevron_right_round), + onPressed: () { + ScaffoldMessenger.of(context).showMaterialBanner(ZetaSystemBanner( + title: 'Title', + context: context, + type: ZetaSystemBannerStatus.warning, + trailing: IconButton( + icon: Icon(ZetaIcons.close_round), + onPressed: () => ScaffoldMessenger.of(context).clearMaterialBanners(), + ), + )); + }, + ), ), ZetaSystemBanner( - type: ZetaSystemBannerType.negativeAppBar, - title: Text('Centered'), - centerTitle: true, - titleIcon: Icon(ZetaIcons.info_round), + type: ZetaSystemBannerStatus.negative, + title: 'Centered', + context: context, + titleStart: true, + leadingIcon: ZetaIcons.info_round, + trailing: IconButton( + icon: Icon(ZetaIcons.chevron_right_round), + onPressed: () { + ScaffoldMessenger.of(context).showMaterialBanner(ZetaSystemBanner( + title: 'Title', + context: context, + type: ZetaSystemBannerStatus.negative, + trailing: IconButton( + icon: Icon(ZetaIcons.close_round), + onPressed: () => ScaffoldMessenger.of(context).clearMaterialBanners(), + ), + )); + }, + ), ), - const SizedBox(height: Dimensions.m), const Divider(), Text('In-Page Banner', style: ZetaTextStyles.displayMedium), - _getTitle('Default Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.neutral), - _getTitle('Info Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.info), - _getTitle('Positive Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.positive), - _getTitle('Warning Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.warning), - _getTitle('Negative Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.negative), - _getTitle('Custom Banner Rounded'), - buildExampleBannerColumn(WidgetSeverity.custom, - customColors: ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue)), - Divider( - height: 50, - color: Colors.transparent, + ZetaInPageBanner( + content: Text(_content), + onClose: () {}, + severity: ZetaWidgetStatus.info, + showIconClose: false, ), - _getTitle('Default Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.neutral, border: BorderType.sharp), - _getTitle('Info Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.info, border: BorderType.sharp), - _getTitle('Positive Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.positive, border: BorderType.sharp), - _getTitle('Warning Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.warning, border: BorderType.sharp), - _getTitle('Negative Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.negative, border: BorderType.sharp), - _getTitle('Custom Banner Sharp'), - buildExampleBannerColumn(WidgetSeverity.custom, - border: BorderType.sharp, - customColors: ZetaWidgetColor(backgroundColor: Colors.blue.shade50, foregroundColor: Colors.blue)), - ] - .divide(const SizedBox( - height: 10, - )) - .toList(), + ZetaInPageBanner( + content: Text(_content), + onClose: () {}, + severity: ZetaWidgetStatus.positive, + showIconClose: true, + title: 'Banner Title', + rounded: false, + ), + ZetaInPageBanner( + content: Text(_content), + onClose: () {}, + severity: ZetaWidgetStatus.warning, + showIconClose: true, + title: 'Banner Title', + actions: [ZetaButton(label: 'Button', onPressed: () {})], + ), + ZetaInPageBanner( + content: Text(_content), + onClose: () {}, + severity: ZetaWidgetStatus.negative, + showIconClose: true, + title: 'Banner Title Banner Title Banner Title Banner Title', + rounded: false, + ), + ZetaInPageBanner( + content: Text(_content), + onClose: () {}, + severity: ZetaWidgetStatus.neutral, + showIconClose: true, + title: 'Banner Title', + ) + ].divide(const SizedBox(height: 10)).toList(), ), ), ), @@ -117,61 +181,25 @@ class BannerExample extends StatelessWidget { Widget _getTitle(String title) => Container(height: 50, child: Center(child: Text(title))); - _getExampleBanner( - WidgetSeverity severity, - BorderType type, { - String? title, - bool showCloseBtn = true, - bool showFirstButton = false, - bool showSecondButton = false, - ZetaWidgetColor? customColors, - IconData? customIcon, - }) => - ZetaInPageBanner( - content: Text(_content), - onClose: () {}, - borderType: type, - severity: severity, - showIconClose: showCloseBtn, - title: title, - firstButton: showFirstButton ? ZetaPageBannerButton(label: 'Button', onPressed: () {}) : null, - secondButton: showSecondButton ? ZetaPageBannerButton(label: 'Button', onPressed: () {}) : null, - customColors: customColors, - customIcon: customIcon, - ); - Column buildExampleBannerColumn( - WidgetSeverity severity, { + ZetaWidgetStatus status, { ZetaWidgetColor? customColors, - BorderType border = BorderType.rounded, + bool rounded = true, IconData? customIcon, }) { - const _title = 'Banner Title'; return Column( mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisSize: MainAxisSize.min, children: [ - _getExampleBanner(severity, border, - title: _title, - showFirstButton: true, - showSecondButton: true, - customColors: customColors, - customIcon: customIcon), - _getExampleBanner(severity, border, title: _title, customColors: customColors, customIcon: customIcon), - Divider(color: Colors.transparent), - _getExampleBanner(severity, border, customColors: customColors, customIcon: customIcon), - Divider(color: Colors.transparent), - _getExampleBanner( - severity, - border, - showCloseBtn: false, - title: _title, - customColors: customColors, + ZetaInPageBanner( + content: Text(_content), + onClose: () {}, + rounded: rounded, + severity: status, + showIconClose: true, + title: 'Banner Title', customIcon: customIcon, ), - Divider(color: Colors.transparent), - _getExampleBanner(severity, border, showCloseBtn: false, customColors: customColors, customIcon: customIcon), - Divider(), ], ); } diff --git a/example/lib/pages/components/bottom_sheet.dart b/example/lib/pages/components/bottom_sheet.dart index 80258b51..92606256 100644 --- a/example/lib/pages/components/bottom_sheet.dart +++ b/example/lib/pages/components/bottom_sheet.dart @@ -14,7 +14,7 @@ class BottomSheetExample extends StatelessWidget { return ExampleScaffold( name: BottomSheetExample.name, child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), + padding: EdgeInsets.all(ZetaSpacing.s), child: Column( children: [ ZetaMenuItem.horizontal( diff --git a/example/lib/pages/components/button_example.dart b/example/lib/pages/components/button_example.dart index 6b875886..7723d4ac 100644 --- a/example/lib/pages/components/button_example.dart +++ b/example/lib/pages/components/button_example.dart @@ -132,8 +132,6 @@ class _ButtonExampleState extends State { ), ]; } - final theme = Zeta.of(context); - final colors = BuildExampleButtonColors(theme: theme); return ExampleScaffold( name: 'Button', @@ -147,17 +145,15 @@ class _ButtonExampleState extends State { child: Column( children: [ Text('Rounded Buttons', style: ZetaTextStyles.displayMedium), - roundedButtonsExample(colors), - Divider(), - Divider(), + Column(children: buttons(BorderType.rounded)), Text('Sharp Buttons', style: ZetaTextStyles.displayMedium), - sharpButtonsExample(colors), - Divider(), - Divider(), + Column(children: buttons(BorderType.sharp)), + Text('Full Buttons', style: ZetaTextStyles.displayMedium), + Column(children: buttons(BorderType.full)), Text('Floating Action Buttons', style: ZetaTextStyles.displayMedium), Text('Tap buttons to change current FAB: ', style: ZetaTextStyles.bodyMedium), Wrap(children: fabs.divide(SizedBox.square(dimension: 10)).toList()), - ], + ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ), ), Expanded(child: const SizedBox()), @@ -166,175 +162,26 @@ class _ButtonExampleState extends State { ), ); } -} - -Widget roundedButtonsExample(BuildExampleButtonColors colors) => Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ..._getZetaButtonExampleRows('Primary', colors.primaryColors), - Divider(), - ..._getZetaButtonExampleRows('Primary Variant', colors.primaryVariantColors), - Divider(), - ..._getZetaButtonExampleRows('Negative', colors.negativeColors, icon: ZetaIcons.delete_round), - Divider(), - ..._getZetaButtonExampleRows('Outlined', colors.outlined, buttonType: ZetaButtonType.outlined), - Divider(), - ..._getZetaButtonExampleRows('Outlined Subtle', colors.outlinedSubtle, buttonType: ZetaButtonType.outlined), - Divider(), - ..._getZetaButtonExampleRows('Text', colors.textColors), - Divider(), - ..._getZetaButtonExampleRows('Text Inverse', colors.textInverseColor), - ], - ); - -Widget sharpButtonsExample(BuildExampleButtonColors colors) => Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ..._getZetaButtonExampleRows('Primary', colors.primaryColors, border: BorderType.sharp), - Divider(), - ..._getZetaButtonExampleRows('Primary Variant', colors.primaryVariantColors, border: BorderType.sharp), - Divider(), - ..._getZetaButtonExampleRows('Negative', colors.negativeColors, - icon: ZetaIcons.delete_sharp, border: BorderType.sharp), - Divider(), - ..._getZetaButtonExampleRows('Outlined', colors.outlined, - buttonType: ZetaButtonType.outlined, border: BorderType.sharp), - Divider(), - ..._getZetaButtonExampleRows('Outlined Subtle', colors.outlinedSubtle, - buttonType: ZetaButtonType.outlined, border: BorderType.sharp), - Divider(), - ..._getZetaButtonExampleRows('Text', colors.textColors, border: BorderType.sharp), - Divider(), - ..._getZetaButtonExampleRows('Text Inverse', colors.textInverseColor, border: BorderType.sharp), - ], - ); - -List _getZetaButtonExampleRows(String label, ZetaButtonColors colors, - {IconData? icon, ZetaButtonType buttonType = ZetaButtonType.filled, BorderType border = BorderType.rounded}) { - return [ - Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text('Large $label')]), - Divider(color: Colors.transparent), - _getRow(buttonType, ZetaWidgetSize.large, colors, border: border, icon: icon), - Divider(color: Colors.transparent), - _getRow(buttonType, ZetaWidgetSize.large, colors, isDisabled: true, border: border, icon: icon), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [Padding(padding: EdgeInsets.all(10), child: Text('Medium $label'))], - ), - _getRow(buttonType, ZetaWidgetSize.medium, colors, border: border, icon: icon), - _getRow(buttonType, ZetaWidgetSize.medium, colors, isDisabled: true, border: border, icon: icon), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [Padding(padding: EdgeInsets.all(10), child: Text('Small $label'))], - ), - _getRow(buttonType, ZetaWidgetSize.small, colors, border: border, icon: icon), - _getRow(buttonType, ZetaWidgetSize.small, colors, isDisabled: true, border: border, icon: icon), - ]; -} - -Widget _getRow(ZetaButtonType type, ZetaWidgetSize size, ZetaButtonColors colors, - {bool isDisabled = false, IconData? icon, BorderType border = BorderType.rounded}) { - final IconData defaultIcon = border == BorderType.rounded ? ZetaIcons.star_round : ZetaIcons.star_sharp; - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _getZetaButtonExample(type, size, colors, isDisabled: isDisabled, border: border), - _getZetaButtonExample(type, size, colors, icon: icon ?? defaultIcon, isDisabled: isDisabled, border: border), - _getZetaButtonExample(type, size, colors, - icon: icon ?? defaultIcon, iconRight: true, isDisabled: isDisabled, border: border), - ], - ); -} - -Widget _getZetaButtonExample(ZetaButtonType buttonType, ZetaWidgetSize size, ZetaButtonColors colors, - {BorderType border = BorderType.rounded, IconData? icon, bool iconRight = false, bool isDisabled = false}) { - if (buttonType == ZetaButtonType.filled) - return ZetaButton.filled( - label: 'Button', - icon: icon, - iconOnRight: iconRight, - borderType: border, - size: size, - colors: colors, - onPressed: isDisabled ? null : () {}, - ); - return ZetaButton.outlined( - label: 'Button', - icon: icon, - iconOnRight: iconRight, - borderType: border, - size: size, - colors: colors, - onPressed: isDisabled ? null : () {}, - ); -} - -class BuildExampleButtonColors { - BuildExampleButtonColors({required this.theme}); - - final Zeta theme; - - ZetaButtonColors get primaryColors { - return ZetaButtonColors( - backgroundColor: ZetaColorBase.blue.shade60, - foregroundColor: ZetaColorBase.greyCool.shade20, - actionColor: ZetaColorBase.blue.shade90, - backgroundDisabled: ZetaColorBase.greyCool.shade30, - foregroundDisabled: ZetaColorBase.greyCool.shade50); - } - - ZetaButtonColors get primaryVariantColors { - return ZetaButtonColors( - backgroundColor: Color(0xFFFFD200), - foregroundColor: ZetaColorBase.greyCool.shade90, - actionColor: Color(0xFFC29500), - backgroundDisabled: ZetaColorBase.greyCool.shade30, - foregroundDisabled: ZetaColorBase.greyCool.shade50); - } - - ZetaButtonColors get negativeColors { - return ZetaButtonColors( - backgroundColor: ZetaColorBase.red.shade60, - foregroundColor: ZetaColorBase.greyCool.shade20, - actionColor: ZetaColorBase.red.shade80, - backgroundDisabled: ZetaColorBase.greyCool.shade30, - foregroundDisabled: ZetaColorBase.greyCool.shade50); - } - - ZetaButtonColors get outlined { - return ZetaButtonColors( - foregroundColor: ZetaColorBase.blue, - actionColor: ZetaColorBase.greyCool.shade30, - backgroundDisabled: ZetaColorBase.greyCool.shade30, - foregroundDisabled: ZetaColorBase.greyCool.shade50, - borderColor: ZetaColorBase.blue); - } - ZetaButtonColors get outlinedSubtle { - return ZetaButtonColors( - foregroundColor: theme.colors.textDefault, - actionColor: ZetaColorBase.greyCool.shade50, - backgroundDisabled: ZetaColorBase.greyCool.shade30, - foregroundDisabled: ZetaColorBase.greyCool.shade50, - iconColor: theme.colors.textDefault, - borderColor: theme.colors.borderDefault); - } - - ZetaButtonColors get textColors { - return ZetaButtonColors( - foregroundColor: ZetaColorBase.blue, - actionColor: ZetaColorBase.greyCool.shade30, - backgroundDisabled: ZetaColorBase.greyCool.shade30, - foregroundDisabled: ZetaColorBase.greyCool.shade50); - } - - ZetaButtonColors get textInverseColor { - return ZetaButtonColors( - foregroundColor: ZetaColorBase.blue.shade40, - actionColor: ZetaColorBase.black, - backgroundDisabled: Colors.transparent, - foregroundDisabled: ZetaColorBase.greyCool); + List buttons(BorderType borderType) { + return List.generate( + ZetaWidgetSize.values.length + 1, + (index) => SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisSize: MainAxisSize.min, + children: List.generate( + ZetaButtonType.values.length, + (index2) => ZetaButton( + label: 'Button', + onPressed: index == 0 ? null : () {}, + type: ZetaButtonType.values[index2], + size: ZetaWidgetSize.values[index == 0 ? 0 : index - 1], + borderType: borderType, + ), + ).divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), + ), + ), + ).reversed.divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(); } } diff --git a/example/lib/pages/components/chip_example.dart b/example/lib/pages/components/chip_example.dart index 1d020481..e859a9ec 100644 --- a/example/lib/pages/components/chip_example.dart +++ b/example/lib/pages/components/chip_example.dart @@ -14,7 +14,7 @@ class ChipExample extends StatelessWidget { return ExampleScaffold( name: ChipExample.name, child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), + padding: EdgeInsets.all(ZetaSpacing.s), child: Column( children: [ ...inputChipExample, diff --git a/example/lib/pages/components/password_input_example.dart b/example/lib/pages/components/password_input_example.dart index b9d2f015..7d8db570 100644 --- a/example/lib/pages/components/password_input_example.dart +++ b/example/lib/pages/components/password_input_example.dart @@ -51,11 +51,11 @@ class _PasswordInputExampleState extends State { return null; }, ), - SizedBox(height: Dimensions.x10), + SizedBox(height: ZetaSpacing.x10), ...passwordInputExampleRow(ZetaWidgetSize.large), - Divider(height: Dimensions.x20), + Divider(height: ZetaSpacing.x20), ...passwordInputExampleRow(ZetaWidgetSize.medium), - Divider(height: Dimensions.x20), + Divider(height: ZetaSpacing.x20), ...passwordInputExampleRow(ZetaWidgetSize.small), ], ), diff --git a/example/lib/pages/theme/color_example.dart b/example/lib/pages/theme/color_example.dart index eeb0d4aa..46698389 100644 --- a/example/lib/pages/theme/color_example.dart +++ b/example/lib/pages/theme/color_example.dart @@ -137,7 +137,7 @@ class _ColorExampleState extends State { return ExampleScaffold( name: ColorExample.name, child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), + padding: EdgeInsets.all(ZetaSpacing.s), child: Column( children: [ MyRow(children: textIcon, title: 'Text and icon styles'), @@ -147,7 +147,7 @@ class _ColorExampleState extends State { MyRow(children: primaries, title: 'Primary colors'), MyRow(children: alerts, title: 'Alert colors'), Row(children: [Text('Full color swatches', style: ZetaTextStyles.displayMedium)]) - .paddingVertical(Dimensions.x8), + .paddingVertical(ZetaSpacing.x8), ...swatches.entries.map( (value) => Row( children: List.generate(10, (index) => 100 - (10 * index)) @@ -182,11 +182,11 @@ class _ColorExampleState extends State { ), ElevatedButton( onPressed: () => setState(() => showGeneratedColors = !showGeneratedColors), - child: const Text('Toggle generated colors').paddingAll(Dimensions.s), - ).paddingAll(Dimensions.s), + child: const Text('Toggle generated colors').paddingAll(ZetaSpacing.s), + ).paddingAll(ZetaSpacing.s), if (showGeneratedColors) Row(children: [Text('Generated color swatches', style: ZetaTextStyles.displayMedium)]) - .paddingVertical(Dimensions.x8), + .paddingVertical(ZetaSpacing.x8), if (showGeneratedColors) ...generatedSwatches.entries.map( (value) => Row( diff --git a/example/lib/pages/theme/typography_example.dart b/example/lib/pages/theme/typography_example.dart index 854b3f70..80e9542b 100644 --- a/example/lib/pages/theme/typography_example.dart +++ b/example/lib/pages/theme/typography_example.dart @@ -102,7 +102,7 @@ class TypographyExample extends StatelessWidget { return ExampleScaffold( name: name, child: SingleChildScrollView( - padding: EdgeInsets.all(Dimensions.s), + padding: EdgeInsets.all(ZetaSpacing.s), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/example/lib/widgets.dart b/example/lib/widgets.dart index 27993c41..ae57919f 100644 --- a/example/lib/widgets.dart +++ b/example/lib/widgets.dart @@ -38,7 +38,7 @@ class ExampleBuilder extends StatelessWidget { height: 7, width: 7, decoration: BoxDecoration(color: Theme.of(context).colorScheme.onSurface, shape: BoxShape.circle), - ).paddingVertical(Dimensions.x9).paddingHorizontal(Dimensions.x4), + ).paddingVertical(ZetaSpacing.x9).paddingHorizontal(ZetaSpacing.x4), if (model.title != null && MediaQuery.of(context).size.width > 767) Expanded(child: Text(model.title!)), Expanded( flex: 5, @@ -55,7 +55,7 @@ class ExampleBuilder extends StatelessWidget { ], ), ), - const SizedBox(height: 7, width: 7).paddingVertical(Dimensions.x9).paddingHorizontal(Dimensions.x4), + const SizedBox(height: 7, width: 7).paddingVertical(ZetaSpacing.x9).paddingHorizontal(ZetaSpacing.x4), ], ); } @@ -97,6 +97,7 @@ class ExampleScaffold extends StatelessWidget { ZetaThemeColorSwitch(), ], ), + backgroundColor: colors.surface, body: SelectionArea( child: child, ), @@ -115,7 +116,7 @@ class CodeExample extends StatelessWidget { final colors = Zeta.of(context).colors; final widget = Container( color: colors.surfaceDisabled, - padding: EdgeInsets.all(Dimensions.x4), + padding: EdgeInsets.all(ZetaSpacing.x4), child: Text(code, style: GoogleFonts.ibmPlexMono(color: colors.textDefault)), ); @@ -133,6 +134,6 @@ class CodeExample extends StatelessWidget { ], ) : widget) - .paddingVertical(Dimensions.x4); + .paddingVertical(ZetaSpacing.x4); } } diff --git a/example/pubspec.lock b/example/pubspec.lock index ed710c29..aafb7441 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" crypto: dependency: transitive description: @@ -220,10 +220,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" nested: dependency: transitive description: @@ -425,18 +425,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -465,10 +465,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" typed_data: dependency: transitive description: @@ -497,10 +497,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" widgetbook: dependency: "direct dev" description: @@ -531,7 +531,7 @@ packages: path: ".." relative: true source: path - version: "0.1.1+22" + version: "0.1.1+23" sdks: - dart: ">=3.1.0 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.10.0" diff --git a/example/test/badge_test.dart b/example/test/badge_test.dart index 74eead34..0028007d 100644 --- a/example/test/badge_test.dart +++ b/example/test/badge_test.dart @@ -9,7 +9,7 @@ void main() { TestWidget( widget: ZetaBadge( label: 'Test Label', - severity: WidgetSeverity.warning, + status: ZetaWidgetStatus.warning, ), ), ); @@ -17,8 +17,8 @@ void main() { final zetaBadgeFinder = find.byType(ZetaBadge); final ZetaBadge badge = tester.firstWidget(zetaBadgeFinder); - expect(badge.borderType, BorderType.rounded); + expect(badge.rounded, true); expect(badge.label, 'Test Label'); - expect(badge.severity, WidgetSeverity.warning); + expect(badge.status, ZetaWidgetStatus.warning); }); } diff --git a/example/test/button_test.dart b/example/test/button_test.dart index 5ea80e6b..cbd6ed03 100644 --- a/example/test/button_test.dart +++ b/example/test/button_test.dart @@ -1,24 +1,21 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:flutter/material.dart'; import 'test_components.dart'; void main() { group('ZetaButton Tests', () { - testWidgets('Initializes with correct Label and Icon', (WidgetTester tester) async { + testWidgets('Initializes with correct Label', (WidgetTester tester) async { await tester.pumpWidget( TestWidget( - widget: ZetaButton( - colors: ZetaButtonColors(), - onPressed: () {}, - label: 'Test Button', - icon: Icons.star, - )), + widget: ZetaButton( + onPressed: () {}, + label: 'Test Button', + ), + ), ); expect(find.text('Test Button'), findsOneWidget); - expect(find.byIcon(Icons.star), findsOneWidget); }); }); @@ -27,7 +24,6 @@ void main() { await tester.pumpWidget( TestWidget( widget: ZetaButton( - colors: ZetaButtonColors(), onPressed: () => callbackTriggered = true, label: 'Test Button', )), diff --git a/example/test/in_page_banner_test.dart b/example/test/in_page_banner_test.dart index 0716b13e..c05081a8 100644 --- a/example/test/in_page_banner_test.dart +++ b/example/test/in_page_banner_test.dart @@ -51,15 +51,23 @@ void main() { testWidgets('ZetaInPageBanner button callbacks work', (WidgetTester tester) async { bool onPressed = false; + final key = GlobalKey(); await tester.pumpWidget( TestWidget( - widget: ZetaInPageBanner( - content: Text('Test'), - firstButton: ZetaPageBannerButton(label: 'Test Button', onPressed: () => onPressed = true), - )), + widget: ZetaInPageBanner( + content: Text('Test'), + actions: [ + ZetaButton( + label: 'Test button', + onPressed: () => onPressed = true, + key: key, + ), + ], + ), + ), ); - await tester.tap(find.text('Test Button')); + await tester.tap(find.byKey(key)); await tester.pumpAndSettle(); expect(onPressed, isTrue); }); diff --git a/example/test/status_label_test.dart b/example/test/status_label_test.dart index 2536a149..b1908792 100644 --- a/example/test/status_label_test.dart +++ b/example/test/status_label_test.dart @@ -19,7 +19,6 @@ void main() { TestWidgetStatusLabel( widget: ZetaStatusLabel( label: 'Custom Icon', - isDefaultIcon: false, customIcon: Icons.person, ), ), diff --git a/example/test/workcloud_indicator_test.dart b/example/test/workcloud_indicator_test.dart index 1186849d..5d7ee833 100644 --- a/example/test/workcloud_indicator_test.dart +++ b/example/test/workcloud_indicator_test.dart @@ -1,42 +1,15 @@ -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; import 'test_components.dart'; void main() { - group('ZetaWorkcloud', () { - testWidgets('ZetaWorkcloud creates status badge', (WidgetTester tester) async { - await tester.pumpWidget( - TestWidget( - widget: ZetaWorkcloudIndicator.status(label: 'Test Label'), - ), - ); - expect(find.byType(ZetaWorkcloudIndicator), findsOneWidget); - }); - }); - testWidgets('ZetaWorkcloud creates priority pill', (WidgetTester tester) async { await tester.pumpWidget( TestWidget( - widget: ZetaWorkcloudIndicator.priorityPill(index: '1'), + widget: ZetaWorkcloudIndicator(index: '1'), ), ); expect(find.text('1'), findsOneWidget); }); - - testWidgets('ZetaWorkcloud custom colors', (WidgetTester tester) async { - final customColor = ZetaWidgetColor(backgroundColor: Colors.pink, foregroundColor: Colors.pink); - await tester.pumpWidget( - TestWidget( - widget: ZetaWorkcloudIndicator.priorityPill( - index: '1', - priorityType: ZetaWorkcloudIndicatorType.custom, - customColors: customColor, - ), - ), - ); - final container = tester.widget(find.byType(Container).first); - expect((container.decoration as BoxDecoration).color, equals(Colors.pink)); - }); } diff --git a/example/widgetbook/components/accordion_widgetbook.dart b/example/widgetbook/components/accordion_widgetbook.dart index 80719c1c..e187d8fa 100644 --- a/example/widgetbook/components/accordion_widgetbook.dart +++ b/example/widgetbook/components/accordion_widgetbook.dart @@ -10,7 +10,7 @@ WidgetbookComponent accordionWidgetBook() { name: 'Accordion', useCases: [ WidgetbookUseCase( - name: 'Accordian', + name: 'Accordion', builder: (context) => TestWidget( themeMode: ThemeMode.dark, widget: Padding( diff --git a/example/widgetbook/components/badges_widgetbook.dart b/example/widgetbook/components/badges_widgetbook.dart index 134980ca..6e3677c6 100644 --- a/example/widgetbook/components/badges_widgetbook.dart +++ b/example/widgetbook/components/badges_widgetbook.dart @@ -20,8 +20,8 @@ WidgetbookComponent badgeWidgetBook() { padding: EdgeInsets.all(20), child: ZetaStatusLabel( label: context.knobs.string(label: 'Label', initialValue: 'Label'), - borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, - severity: context.knobs.list(label: 'Status', options: WidgetSeverity.values), + rounded: context.knobs.boolean(label: 'Rounded'), + status: context.knobs.list(label: 'Status', options: ZetaWidgetStatus.values), customIcon: context.knobs.list( label: 'Icon', options: [ @@ -38,7 +38,6 @@ WidgetbookComponent badgeWidgetBook() { return ''; }, ), - isDefaultIcon: context.knobs.boolean(label: 'Use default Icon'), ), ), ], @@ -57,7 +56,7 @@ WidgetbookComponent badgeWidgetBook() { child: ZetaPriorityPill( index: context.knobs.int.slider(label: 'Index'), priority: context.knobs.string(label: 'Priority', initialValue: 'Priority'), - borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + rounded: context.knobs.boolean(label: 'Rounded'), ), ), ], @@ -75,8 +74,8 @@ WidgetbookComponent badgeWidgetBook() { padding: EdgeInsets.all(20), child: ZetaBadge( label: context.knobs.string(label: 'Label', initialValue: 'Label'), - borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, - severity: context.knobs.list(label: 'Status', options: WidgetSeverity.values), + rounded: context.knobs.boolean(label: 'Rounded'), + status: context.knobs.list(label: 'Status', options: ZetaWidgetStatus.values), ), ), ], @@ -94,9 +93,6 @@ WidgetbookComponent badgeWidgetBook() { padding: EdgeInsets.all(20), child: ZetaIndicator( type: context.knobs.list(label: 'Type', options: ZetaIndicatorType.values), - backgroundColor: context.knobs.colorOrNull(label: 'Background Color'), - borderColor: context.knobs.colorOrNull(label: 'Border Color'), - foregroundColor: context.knobs.colorOrNull(label: 'Foreground Color'), icon: context.knobs.list( label: 'Icon', options: [ @@ -113,8 +109,7 @@ WidgetbookComponent badgeWidgetBook() { return ''; }, ), - inverseBorder: context.knobs.boolean(label: 'Inverse Border'), - rounded: context.knobs.boolean(label: 'Rounded'), + inverse: context.knobs.boolean(label: 'Inverse Border'), size: context.knobs.list(label: 'Size', options: ZetaIndicatorSize.values), value: context.knobs.int.slider(label: 'Value'), ), @@ -134,7 +129,7 @@ WidgetbookComponent badgeWidgetBook() { padding: EdgeInsets.all(20), child: ZetaTag( label: context.knobs.string(label: 'Label', initialValue: 'Tag'), - borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + rounded: context.knobs.boolean(label: 'Rounded'), direction: context.knobs.list(label: 'Direction', options: ZetaTagDirection.values), ), ) @@ -155,12 +150,27 @@ WidgetbookComponent badgeWidgetBook() { Padding( padding: EdgeInsets.all(20), child: ZetaWorkcloudIndicator( - index: context.knobs.string(label: 'Index', initialValue: '1'), - isStatusBadge: context.knobs.boolean(label: 'Status Badge', initialValue: false), - label: context.knobs.string(label: 'Label', initialValue: 'Label'), - prioritySize: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), - priorityType: context.knobs.list(label: 'Type', options: ZetaWorkcloudIndicatorType.values), - ), + index: context.knobs.string(label: 'Index', initialValue: '1'), + label: context.knobs.string(label: 'Label', initialValue: 'Label'), + prioritySize: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), + priorityType: context.knobs.list(label: 'Type', options: ZetaWorkcloudIndicatorType.values), + icon: context.knobs.listOrNull( + label: 'Icon', + options: [ + ZetaIcons.star_half_round, + ZetaIcons.add_alert_round, + ZetaIcons.add_box_round, + ZetaIcons.barcode_round, + ], + initialOption: null, + labelBuilder: (value) { + if (value == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if (value == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if (value == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if (value == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + )), ) ], ), diff --git a/example/widgetbook/components/banner_widgetbook.dart b/example/widgetbook/components/banner_widgetbook.dart index 7dbfbd5d..fe571767 100644 --- a/example/widgetbook/components/banner_widgetbook.dart +++ b/example/widgetbook/components/banner_widgetbook.dart @@ -17,12 +17,28 @@ WidgetbookComponent BannerWidgetBook() { child: Column( children: [ ZetaSystemBanner( - title: Text(context.knobs.string(label: 'Title', initialValue: 'Banner Title')), - type: context.knobs.list(label: 'Type', options: ZetaSystemBannerType.values), - titleIcon: context.knobs.boolean(label: 'Leading Icon') ? Icon(ZetaIcons.info_round) : null, - centerTitle: context.knobs.boolean(label: 'Center title'), - actions: context.knobs.boolean(label: 'Trailing Icon') - ? [IconButton(icon: Icon(ZetaIcons.chevron_right_round), onPressed: () {})] + context: context, + title: context.knobs.string(label: 'Title', initialValue: 'Banner Title'), + type: context.knobs.list(label: 'Type', options: ZetaSystemBannerStatus.values), + leadingIcon: context.knobs.list( + label: 'Icon', + options: [ + ZetaIcons.star_half_round, + ZetaIcons.add_alert_round, + ZetaIcons.add_box_round, + ZetaIcons.barcode_round, + ], + labelBuilder: (value) { + if (value == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if (value == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if (value == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if (value == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + ), + titleStart: context.knobs.boolean(label: 'Center title'), + trailing: context.knobs.boolean(label: 'Trailing Icon') + ? IconButton(icon: Icon(ZetaIcons.chevron_right_round), onPressed: () {}) : null, ), ], @@ -46,16 +62,26 @@ WidgetbookComponent BannerWidgetBook() { 'Lorem ipsum dolor sit amet, conse ctetur cididunt ut labore et do lore magna aliqua.', ), ), - severity: context.knobs.list(label: 'Severity', options: WidgetSeverity.values), + severity: context.knobs.list(label: 'Severity', options: ZetaWidgetStatus.values), showIconClose: context.knobs.boolean(label: 'Show Close icon'), title: context.knobs.string(label: 'Title', initialValue: 'Title'), - borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, - firstButton: context.knobs.boolean(label: 'First Button') - ? ZetaPageBannerButton(onPressed: () {}, label: 'Button') - : null, - secondButton: context.knobs.boolean(label: 'Second Button') - ? ZetaPageBannerButton(onPressed: () {}, label: 'Button') - : null, + rounded: context.knobs.boolean(label: 'Rounded'), + actions: () { + final x = context.knobs.list(label: 'Show Buttons', options: [0, 1, 2]); + + if (x == 1) { + return [ + ZetaButton(label: 'Button 1', onPressed: () {}), + ]; + } + if (x == 2) { + return [ + ZetaButton(label: 'Button 1', onPressed: () {}), + ZetaButton(label: 'Button 2', onPressed: () {}) + ]; + } + return []; + }(), customIcon: context.knobs.list( label: 'Icon', options: [ diff --git a/example/widgetbook/components/button_widgetbook.dart b/example/widgetbook/components/button_widgetbook.dart index 104e0827..91b2fc4b 100644 --- a/example/widgetbook/components/button_widgetbook.dart +++ b/example/widgetbook/components/button_widgetbook.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/components/button_example.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; import '../../test/test_components.dart'; @@ -13,56 +12,13 @@ WidgetbookComponent buttonWidgetBook() { WidgetbookUseCase( name: 'Button', builder: (context) { - final buttonColors = BuildExampleButtonColors(theme: Zeta.of(context)); - List all = [ - buttonColors.primaryColors, - buttonColors.primaryVariantColors, - buttonColors.negativeColors, - buttonColors.outlined, - buttonColors.outlinedSubtle, - buttonColors.textColors, - buttonColors.textInverseColor, - ]; - return TestWidget( widget: Padding( padding: EdgeInsets.all(20), child: ZetaButton( label: context.knobs.string(label: 'Text', initialValue: 'Button'), - colors: context.knobs.list( - label: 'Colors', - options: all, - labelBuilder: (value) { - if (value.backgroundColor == buttonColors.primaryColors.backgroundColor) return 'Primary'; - if (value.backgroundColor == buttonColors.primaryVariantColors.backgroundColor) - return 'Primary Variant'; - if (value.backgroundColor == buttonColors.negativeColors.backgroundColor) return 'Negative'; - if (value.foregroundColor == buttonColors.textColors.foregroundColor) return 'Text'; - if (value.actionColor == buttonColors.outlined.actionColor) return 'Outlined'; - if (value.actionColor == buttonColors.outlinedSubtle.actionColor) return 'Outline Subtle'; - if (value.actionColor == buttonColors.textInverseColor.actionColor) return 'Text Inverse'; - return ''; - }, - ), onPressed: context.knobs.boolean(label: 'Disabled') ? null : () {}, borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, - icon: context.knobs.list( - label: 'Icon', - options: [ - ZetaIcons.star_half_round, - ZetaIcons.add_alert_round, - ZetaIcons.add_box_round, - ZetaIcons.barcode_round, - ], - labelBuilder: (value) { - if (value == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; - if (value == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; - if (value == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; - if (value == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; - return ''; - }, - ), - iconOnRight: context.knobs.boolean(label: 'Icon on right'), size: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), type: context.knobs.list(label: 'Type', options: ZetaButtonType.values), ), diff --git a/example/widgetbook/components/password_input_widgetbook.dart b/example/widgetbook/components/password_input_widgetbook.dart index 649ac87a..16b0a036 100644 --- a/example/widgetbook/components/password_input_widgetbook.dart +++ b/example/widgetbook/components/password_input_widgetbook.dart @@ -38,7 +38,7 @@ class _PasswordState extends State<_Password> { key: _formKey, child: TestWidget( widget: Padding( - padding: EdgeInsets.all(Dimensions.x5), + padding: EdgeInsets.all(ZetaSpacing.x5), child: Column( children: [ ConstrainedBox( diff --git a/example/widgetbook/theme/color_widgetbook.dart b/example/widgetbook/theme/color_widgetbook.dart index 247298bd..8beaf9cb 100644 --- a/example/widgetbook/theme/color_widgetbook.dart +++ b/example/widgetbook/theme/color_widgetbook.dart @@ -85,18 +85,18 @@ class ColorBody extends StatelessWidget { }; return Container( - padding: const EdgeInsets.symmetric(horizontal: Dimensions.l), + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.l), child: SingleChildScrollView( child: Column( children: [ - const SizedBox(height: Dimensions.l), + 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(Dimensions.x8), + .paddingVertical(ZetaSpacing.x8), ...swatches.entries.map( (value) { return Row( @@ -134,7 +134,7 @@ class ColorBody extends StatelessWidget { ); }, ), - const SizedBox(height: Dimensions.l), + const SizedBox(height: ZetaSpacing.l), ], ), ), diff --git a/example/widgetbook/theme/typography_widgetbook.dart b/example/widgetbook/theme/typography_widgetbook.dart index 21e3a59f..6eb20fe5 100644 --- a/example/widgetbook/theme/typography_widgetbook.dart +++ b/example/widgetbook/theme/typography_widgetbook.dart @@ -30,7 +30,7 @@ WidgetbookComponent textWidgetBook() { name: 'Text styles', builder: (context) => Container( color: Theme.of(context).colorScheme.background, - padding: const EdgeInsets.all(Dimensions.l), + 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( diff --git a/lib/src/components/accordion/accordion.dart b/lib/src/components/accordion/accordion.dart index e0d4016a..928c3c79 100644 --- a/lib/src/components/accordion/accordion.dart +++ b/lib/src/components/accordion/accordion.dart @@ -2,52 +2,49 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -/// Component [ZetaAccordion] +/// Zeta Accordion component. +/// +/// The accordion is a control element comprising a vertically stacked list of items, +/// such as labels or thumbnails. Each item can be "expanded" or "collapsed" to reveal +/// the content associated with that item. There can be zero expanded items, exactly one, +/// or more than one item expanded at a time, depending on the configuration. class ZetaAccordion extends StatelessWidget { - /// The constructor of the component [ZetaAccordion] + /// The constructor of the component [ZetaAccordion]. const ZetaAccordion({ super.key, required this.children, - this.separator, - this.spaceBetween = 20.0, - this.margin, this.rounded = true, this.contained = false, }); - /// List of [ZetaAccordionSection] to show in [ZetaAccordion] + /// List of [ZetaAccordionSection] to show in [ZetaAccordion]. final List children; - /// Custom separator between the [ZetaAccordionSection]s in the list `children`. - /// Default is empty space with height of `spaceBetween`. - final Widget? separator; - - /// The height of the space between [ZetaAccordionSection]s `children`. - /// Default is 20. - final double spaceBetween; - - /// The space around the [ZetaAccordion]. Default is `zero`. - final EdgeInsets? margin; - + /// {@template zeta-component-rounded} /// Sets rounded or sharp border of the containing box and the icon style. - /// Default is `true`. + /// + /// Defaults to `true`. + /// {@endtemplate} final bool rounded; /// Determines if the [ZetaAccordionSection]s should be in a box. - /// Default is `false` + /// + /// Defaults to `false`. final bool contained; @override Widget build(BuildContext context) { - return ListView.separated( - padding: margin ?? EdgeInsets.zero, - shrinkWrap: true, - itemCount: children.length, - itemBuilder: (context, index) => children[index].copyWith( - rounded: rounded, - contained: contained, + return DecoratedBox( + decoration: BoxDecoration( + borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, + border: Border(top: BorderSide(color: Zeta.of(context).colors.cool.shade40)), + ), + child: ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: children.length, + itemBuilder: (context, index) => children[index].copyWith(rounded: rounded, contained: contained), ), - separatorBuilder: (context, index) => separator ?? SizedBox(height: spaceBetween), ); } @@ -55,13 +52,13 @@ class ZetaAccordion extends StatelessWidget { void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(DiagnosticsProperty('spaceBetween', spaceBetween)) - ..add(DiagnosticsProperty('margin', margin)) ..add(DiagnosticsProperty('rounded', rounded)) ..add(DiagnosticsProperty('contained', contained)); } } +// TODO(thelukewalton): Consider changing this to improve developer experience. + /// The element for the `children` of [ZetaAccordion] class ZetaAccordionSection extends StatefulWidget { /// The constructor of the [ZetaAccordionSection] @@ -176,7 +173,7 @@ class _ZetaAccordionSectionState extends State with Ticker color: _disabled ? zetaColors.borderDisabled : zetaColors.borderDefault, ) : null, - borderRadius: widget.rounded ? BorderRadius.circular(Dimensions.xxs) : null, + borderRadius: widget.rounded ? ZetaRadius.minimal : ZetaRadius.none, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -193,6 +190,7 @@ class _ZetaAccordionSectionState extends State with Ticker _controller.forward(); } }), + hoverColor: Zeta.of(context).colors.cool.shade20, child: Padding( padding: const EdgeInsets.all(16), child: Row( @@ -205,7 +203,7 @@ class _ZetaAccordionSectionState extends State with Ticker child: Flexible(child: widget.title), ), Padding( - padding: const EdgeInsets.only(left: 16), + padding: const EdgeInsets.only(left: ZetaSpacing.x4), child: Icon( _isOpen ? (widget.rounded ? ZetaIcons.remove_round : ZetaIcons.remove_sharp) @@ -221,11 +219,8 @@ class _ZetaAccordionSectionState extends State with Ticker sizeFactor: _animation, axisAlignment: -1, child: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: DefaultTextStyle( - style: ZetaTextStyles.titleSmall, - child: widget.body, - ), + padding: const EdgeInsets.fromLTRB(ZetaSpacing.x4, ZetaSpacing.x0, ZetaSpacing.x4, ZetaSpacing.x4), + child: DefaultTextStyle(style: ZetaTextStyles.titleSmall, child: widget.body), ), ), ], diff --git a/lib/src/components/avatars/avatar.dart b/lib/src/components/avatars/avatar.dart index 1c6f2fbb..77055c6b 100644 --- a/lib/src/components/avatars/avatar.dart +++ b/lib/src/components/avatars/avatar.dart @@ -3,6 +3,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; +// TODO(thelukewalton): Think more about this. + /// [ZetaAvatar] type enum ZetaAvatarType { /// [image] shows a picture or a placeholder @@ -239,17 +241,8 @@ class ZetaAvatar extends StatelessWidget { child: innerContent, ), ), - if (badge != null) - Positioned( - right: 1, - child: badge!, - ), - if (specialStatus != null) - Positioned( - right: 1, - bottom: 1, - child: specialStatus!, - ), + if (badge != null) Positioned(right: 1, child: badge!), + if (specialStatus != null) Positioned(right: 1, bottom: 1, child: specialStatus!), ], ); } diff --git a/lib/src/components/badges/badge.dart b/lib/src/components/badges/badge.dart index ceeabe37..c302bdb4 100644 --- a/lib/src/components/badges/badge.dart +++ b/lib/src/components/badges/badge.dart @@ -3,119 +3,55 @@ import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -///Zeta Badge +/// Zeta Badge. +/// +/// Text badges notify users of line items that need attention. class ZetaBadge extends StatelessWidget { - ///Constructs [ZetaBadge] + ///Constructs [ZetaBadge]. const ZetaBadge({ required this.label, - this.severity = WidgetSeverity.info, - this.borderType = BorderType.rounded, - this.badgeSize = const Size(Dimensions.x9, Dimensions.x5), - this.customColor, + this.status = ZetaWidgetStatus.info, + this.rounded = true, super.key, }); - ///The shape of the badge - /// - /// Defaults to rounded - final BorderType borderType; + /// {@macro zeta-component-rounded} + final bool rounded; - ///Indicates the severity of the badge - ///If set to "custom", [customColor] should be picked - ///Defaults to "info" - final WidgetSeverity severity; + /// {@template zeta-component-badge-status} + /// Indicates the status of the badge. + /// + /// Defaults to "info" + /// {@endtemplate} + final ZetaWidgetStatus status; - ///Label of the badge + /// Label of the badge. final String label; - ///The size of the badge - final Size badgeSize; - - ///Custom color of the badge - final Color? customColor; - @override Widget build(BuildContext context) { - final theme = Zeta.of(context); + final Color backgroundColor = status.colorSwatch(context); + return Container( - height: badgeSize.height, - constraints: BoxConstraints(minWidth: badgeSize.width), - decoration: _buildBadgeDecoration(theme), - child: Center( - child: _buildBadgeContent(theme), + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x1, vertical: ZetaSpacing.x1 / 2), + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.minimal, ), - ); - } - - BoxDecoration _buildBadgeDecoration(Zeta theme) { - return BoxDecoration( - color: _badgeBackgroundColor(theme), - borderRadius: BorderRadius.circular( - borderType == BorderType.rounded ? Dimensions.x1 : 0.0, + child: Text( + label, + style: ZetaTextStyles.labelSmall.apply(color: backgroundColor.onColor), + overflow: TextOverflow.ellipsis, ), ); } - Widget _buildBadgeContent(Zeta theme) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: Padding( - padding: const EdgeInsets.fromLTRB(4, 2, 4, 2), - child: Text( - label, - style: ZetaTextStyles.labelSmall.apply(color: _badgeForegroundColor(theme)), - overflow: TextOverflow.ellipsis, - ), - ), - ), - ], - ); - } - - Color _badgeBackgroundColor(Zeta theme) { - switch (severity) { - case WidgetSeverity.info: - return theme.colors.purple; - case WidgetSeverity.positive: - return theme.colors.green; - case WidgetSeverity.warning: - return theme.colors.orange; - case WidgetSeverity.negative: - return theme.colors.red; - case WidgetSeverity.neutral: - return theme.colors.borderDisabled; - case WidgetSeverity.custom: - return customColor ?? theme.colors.surfaceDisabled; - } - } - - Color _badgeForegroundColor(Zeta theme) { - switch (severity) { - case WidgetSeverity.info: - return theme.colors.textDefault; - case WidgetSeverity.positive: - return theme.colors.black; - case WidgetSeverity.warning: - return theme.colors.textInverse; - case WidgetSeverity.negative: - return theme.colors.textDefault; - case WidgetSeverity.neutral: - return theme.colors.white; - case WidgetSeverity.custom: - return theme.colors.white; - } - } - @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(EnumProperty('borderType', borderType)) - ..add(EnumProperty('severity', severity)) ..add(StringProperty('label', label)) - ..add(DiagnosticsProperty('badgeSize', badgeSize)) - ..add(ColorProperty('customColor', customColor)); + ..add(EnumProperty('status', status)) + ..add(DiagnosticsProperty('rounded', rounded)); } } diff --git a/lib/src/components/badges/indicator.dart b/lib/src/components/badges/indicator.dart index 1ceeb78f..084803bb 100644 --- a/lib/src/components/badges/indicator.dart +++ b/lib/src/components/badges/indicator.dart @@ -2,117 +2,82 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -/// [ZetaIndicator] type +/// [ZetaIndicator] type. enum ZetaIndicatorType { - /// [icon] shows an icon + /// Shows an icon on [ZetaIndicator]. Defaults to [ZetaIcons.star_round]. icon, - /// [notification] shows a number provided with the `value` parameter + /// Shows a number on [ZetaIndicator] from provided [ZetaIndicator.value]. notification, } -/// [ZetaIndicator] size +/// [ZetaIndicator] size. enum ZetaIndicatorSize { - /// [large] 16 pixels + /// Largest size - [ZetaSpacing.x4] 16x16 pixels. large, - /// [medium] 12 pixels + /// Medium size - [ZetaSpacing.x3] - 12x12 pixels for [ZetaIndicatorType.icon] or [ZetaSpacing.x3_5] - 14x14 pixels for [ZetaIndicatorType.notification]. medium, - /// [small] 8 pixels + /// Smallest size - [ZetaSpacing.x2] - 8x8 pixels. small, } -/// ZetaIndicator component +/// ZetaIndicator. +/// +/// Indicators are used to show the status of a user or any messages/notifications they might have. class ZetaIndicator extends StatelessWidget { - /// Constructor for [ZetaIndicator] + /// Constructor for [ZetaIndicator]. ZetaIndicator({ super.key, required this.type, this.size = ZetaIndicatorSize.large, this.icon, - this.rounded = true, this.value, - this.backgroundColor, - this.foregroundColor, - this.borderColor, - this.inverseBorder = false, + this.inverse = false, }) { - _sizePixels = getSizePixels(size, type); + _sizePixels = _getSizePixels(size, type); } - /// Constructor for [ZetaIndicator] of type `icon` + /// Constructor for [ZetaIndicator] of type [ZetaIndicatorType.icon]. factory ZetaIndicator.icon({ ZetaIndicatorSize size = ZetaIndicatorSize.large, - Color? backgroundColor, - Color? foregroundColor, - Color? borderColor, bool inverseBorder = false, Icon? icon, - bool rounded = true, }) => ZetaIndicator( type: ZetaIndicatorType.icon, size: size, - backgroundColor: backgroundColor, - foregroundColor: foregroundColor, - borderColor: borderColor, - inverseBorder: inverseBorder, + inverse: inverseBorder, icon: icon, - rounded: rounded, ); - /// Constructor for [ZetaIndicator] of type `icon` + /// Constructor for [ZetaIndicator] of type [ZetaIndicatorType.notification]. factory ZetaIndicator.notification({ ZetaIndicatorSize size = ZetaIndicatorSize.large, - Color? backgroundColor, - Color? foregroundColor, - Color? borderColor, bool inverseBorder = false, int? value, }) => ZetaIndicator( type: ZetaIndicatorType.notification, size: size, - backgroundColor: backgroundColor, - foregroundColor: foregroundColor, - borderColor: borderColor, - inverseBorder: inverseBorder, + inverse: inverseBorder, value: value, ); - /// The type of the [ZetaIndicator] - icon or notification + /// The type of the [ZetaIndicator] - icon or notification. final ZetaIndicatorType type; /// The size of the [ZetaIndicator]. Default is [ZetaIndicatorSize.large] final ZetaIndicatorSize size; - /// Background color. - /// Default is blue for [ZetaIndicatorType.icon] - /// and negative for [ZetaIndicatorType.notification]. - final Color? backgroundColor; + /// Inverse the border color. + final bool inverse; - /// Foreground color. Default is white. - final Color? foregroundColor; - - /// Border color. - /// Default is surfacePrimary or textDefault - /// depending on theme mode (light or dark) and [inverseBorder]. - final Color? borderColor; - - /// Inverse the border color. Not considered, if [borderColor] is provided. - final bool inverseBorder; - - /// Indicator icon, default: `ZetaIcons.star_round` + /// Indicator icon, default: `ZetaIcons.star_round`. final Icon? icon; - /// Determines if the default icon should be rounded or sharp: - /// `ZetaIcons.star_round` or `ZetaIcons.star_sharp`. - /// Default is `true`. - /// Not taken into account, if [icon] is provided. - final bool rounded; - - /// Value for the type `notification` + /// Value for the type `notification`. final int? value; late final double _sizePixels; @@ -120,127 +85,72 @@ class ZetaIndicator extends StatelessWidget { @override Widget build(BuildContext context) { final zetaColors = Zeta.of(context).colors; + final Color backgroundColor = (type == ZetaIndicatorType.icon ? zetaColors.blue : zetaColors.negative); + final Color foregroundColor = backgroundColor.onColor; return Container( - width: _sizePixels + 4, - height: _sizePixels + 4, + width: _sizePixels + ZetaSpacing.x1, + height: _sizePixels + ZetaSpacing.x1, decoration: BoxDecoration( - color: borderColor ?? (inverseBorder ? zetaColors.textDefault : zetaColors.surfacePrimary), + color: (inverse ? foregroundColor : Colors.transparent), borderRadius: BorderRadius.circular(20), ), child: Center( child: Container( width: _sizePixels, height: _sizePixels, - decoration: BoxDecoration( - color: backgroundColor ?? (type == ZetaIndicatorType.icon ? zetaColors.blue : zetaColors.negative), - borderRadius: BorderRadius.circular(16), - ), + decoration: BoxDecoration(color: backgroundColor, borderRadius: BorderRadius.circular(ZetaSpacing.x4)), child: ClipRRect( - borderRadius: BorderRadius.circular(16), + borderRadius: BorderRadius.circular(ZetaSpacing.x4), clipBehavior: Clip.hardEdge, - child: size == ZetaIndicatorSize.small - ? null - : _InnerContent( - type: type, - size: size, - sizePixels: _sizePixels, - icon: icon, - rounded: rounded, - value: value, - foregroundColor: foregroundColor, - ), + child: size == ZetaIndicatorSize.small ? null : _buildContent(foregroundColor), ), ), ), ); } - /// Returns the size of [ZetaIndicatorSize] in pixels - static double getSizePixels(ZetaIndicatorSize size, ZetaIndicatorType type) { - switch (size) { - case ZetaIndicatorSize.large: - return 16; - case ZetaIndicatorSize.medium: - return type == ZetaIndicatorType.icon ? 12 : 14; - case ZetaIndicatorSize.small: - return 8; - } - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', type)) - ..add(DiagnosticsProperty('size', size)) - ..add(DiagnosticsProperty('value', value)) - ..add(DiagnosticsProperty('icon', icon)) - ..add(DiagnosticsProperty('rounded', rounded)) - ..add(DiagnosticsProperty('backgroundColor', backgroundColor)) - ..add(DiagnosticsProperty('foregroundColor', foregroundColor)) - ..add(DiagnosticsProperty('borderColor', borderColor)) - ..add(DiagnosticsProperty('inverseBorder', inverseBorder)); - } -} - -class _InnerContent extends StatelessWidget { - const _InnerContent({ - required this.type, - required this.size, - required this.sizePixels, - this.icon, - this.rounded = true, - this.value, - this.foregroundColor, - }); - - final ZetaIndicatorType type; - final ZetaIndicatorSize size; - final double sizePixels; - final Icon? icon; - final bool rounded; - final int? value; - final Color? foregroundColor; - - @override - Widget build(BuildContext context) { - final defaultColor = Zeta.of(context).colors.white; + Widget _buildContent(Color foregroundColor) { switch (type) { case ZetaIndicatorType.icon: final iconSize = _getIconSize(size); return Center( child: IconTheme( - data: IconThemeData( - color: foregroundColor ?? defaultColor, - size: iconSize, - ), - child: icon ?? Icon(rounded ? ZetaIcons.star_round : ZetaIcons.star_sharp), + data: IconThemeData(color: foregroundColor, size: iconSize), + child: icon ?? const Icon(ZetaIcons.star_round), ), ); case ZetaIndicatorType.notification: - final strVal = value == null ? '' : value!.abs().toString(); - return Center( child: Text( - strVal.length > 1 ? '9+' : strVal, - textAlign: strVal.length == 1 ? TextAlign.center : TextAlign.right, - style: (size == ZetaIndicatorSize.large ? ZetaTextStyles.labelIndicator : ZetaTextStyles.labelTiny).apply( - color: Zeta.of(context).colors.white, - ), + value.formatMaxChars(), + style: (size == ZetaIndicatorSize.large ? ZetaTextStyles.labelIndicator : ZetaTextStyles.labelTiny) + .apply(color: foregroundColor), ), ); } } + /// Returns the size of [ZetaIndicatorSize] in pixels + double _getSizePixels(ZetaIndicatorSize size, ZetaIndicatorType type) { + switch (size) { + case ZetaIndicatorSize.large: + return ZetaSpacing.x4; + case ZetaIndicatorSize.medium: + return type == ZetaIndicatorType.icon ? ZetaSpacing.x3 : ZetaSpacing.x3_5; + case ZetaIndicatorSize.small: + return ZetaSpacing.x2; + } + } + double _getIconSize(ZetaIndicatorSize size) { switch (size) { case ZetaIndicatorSize.large: - return 11; + return ZetaSpacing.x3; case ZetaIndicatorSize.medium: - return 8; + return ZetaSpacing.x2; case ZetaIndicatorSize.small: - return 1; + return ZetaSpacing.x0; } } @@ -250,10 +160,8 @@ class _InnerContent extends StatelessWidget { properties ..add(DiagnosticsProperty('type', type)) ..add(DiagnosticsProperty('size', size)) - ..add(DiagnosticsProperty('sizePixels', sizePixels)) ..add(DiagnosticsProperty('value', value)) ..add(DiagnosticsProperty('icon', icon)) - ..add(DiagnosticsProperty('rounded', rounded)) - ..add(DiagnosticsProperty('foregroundColor', foregroundColor)); + ..add(DiagnosticsProperty('inverseBorder', inverse)); } } diff --git a/lib/src/components/badges/priority_pill.dart b/lib/src/components/badges/priority_pill.dart index b52e2b57..a95002c0 100644 --- a/lib/src/components/badges/priority_pill.dart +++ b/lib/src/components/badges/priority_pill.dart @@ -3,86 +3,70 @@ import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -///Zeta Priority Pill +///Zeta Priority Pill. +/// +/// This badge is used to indicate the order of importance. class ZetaPriorityPill extends StatelessWidget { ///Constructs [ZetaPriorityPill] const ZetaPriorityPill({ required this.index, required this.priority, - this.borderType = BorderType.sharp, + this.rounded = true, super.key, }); - ///Border type of the badge - final BorderType borderType; + /// {@macro zeta-component-rounded} + final bool rounded; - ///Priority number + /// Leading number in component. final int index; - ///Priority label + /// Text in main part of component. final String priority; - bool get _isBorderRounded => borderType == BorderType.rounded; - @override Widget build(BuildContext context) { final theme = Zeta.of(context); + final backgroundColor = theme.colors.primary; + final Color foregroundColor = backgroundColor.onColor; + return DecoratedBox( - decoration: _buildBoxDecoration(theme), + decoration: BoxDecoration( + borderRadius: rounded ? ZetaRadius.full : ZetaRadius.none, + color: backgroundColor.shade10, + ), child: Row( mainAxisSize: MainAxisSize.min, children: [ - _buildIndexContainer(theme), - _buildPriorityText(), + Container( + alignment: Alignment.center, + height: ZetaSpacing.x7, + width: ZetaSpacing.x7, + decoration: BoxDecoration( + shape: rounded ? BoxShape.circle : BoxShape.rectangle, + color: backgroundColor, + ), + child: Text(index.formatMaxChars(), style: ZetaTextStyles.bodyMedium.apply(color: foregroundColor)), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x2, vertical: ZetaSpacing.x1), + child: Text( + priority, + style: ZetaTextStyles.bodyMedium, + overflow: TextOverflow.ellipsis, + ), + ), ], ), ); } - BoxDecoration _buildBoxDecoration(Zeta theme) { - return BoxDecoration( - borderRadius: BorderRadius.circular( - _isBorderRounded ? Dimensions.l : Dimensions.x0, - ), - color: theme.colors.blue.shade10, - ); - } - - Widget _buildIndexContainer(Zeta theme) { - return Container( - alignment: Alignment.center, - height: Dimensions.x7, - width: _isBorderRounded ? Dimensions.x7 : Dimensions.x6, - decoration: BoxDecoration( - shape: _isBorderRounded ? BoxShape.circle : BoxShape.rectangle, - color: theme.colors.blue.shade60, - ), - child: Text( - '$index', - style: ZetaTextStyles.bodyMedium.apply(color: theme.colors.white), - ), - ); - } - - Widget _buildPriorityText() { - return Flexible( - child: Padding( - padding: const EdgeInsets.fromLTRB(8, 4, 8, 4), - child: Text( - priority, - style: ZetaTextStyles.bodyMedium, - overflow: TextOverflow.ellipsis, - ), - ), - ); - } - @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(EnumProperty('borderType', borderType)) ..add(IntProperty('index', index)) - ..add(StringProperty('priority', priority)); + ..add(StringProperty('priority', priority)) + ..add(DiagnosticsProperty('rounded', rounded)); } } diff --git a/lib/src/components/badges/status_label.dart b/lib/src/components/badges/status_label.dart index 7faed37c..0da9ce8f 100644 --- a/lib/src/components/badges/status_label.dart +++ b/lib/src/components/badges/status_label.dart @@ -2,158 +2,67 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -///Zeta Status Label +/// Zeta Status Label. +/// +/// To help some information, labels, or errors stand out, we present them with badges. +/// They can look like buttons, but users can’t select them. They just guide users to things they should pay attention to. class ZetaStatusLabel extends StatelessWidget { ///Constructs [ZetaStatusLabel]. const ZetaStatusLabel({ + super.key, required this.label, - this.severity = WidgetSeverity.neutral, - this.isDefaultIcon = true, + this.rounded = true, + this.status = ZetaWidgetStatus.info, this.customIcon, - this.borderType = BorderType.sharp, - this.labelSize = const Size(67, 24), - this.borderWidth = 1, - this.customColors, - this.customIconSize = 20.0, - super.key, }); - ///The type of border to display - /// - /// Defaults to sharp - final BorderType borderType; - - ///Width of the label border - /// - /// Defaults to 1 - final double borderWidth; + /// {@zeta-component-rounded} + final bool rounded; - ///Size of the label - final Size labelSize; + /// {@macro zeta-component-badge-status} + final ZetaWidgetStatus status; - ///Widget Severity - /// - /// Defaults to "neutral" - final WidgetSeverity severity; - - ///Label + /// Text displayed on label. final String label; - ///Colors for the label - final ZetaWidgetColor? customColors; - - ///Whether the icon is the default icon - /// - ///Defaults to true - final bool isDefaultIcon; - - ///Custom icon + /// Optional custom icon. If null, default circle icon is used. final IconData? customIcon; - ///The size of the custom icon - /// - ///Defaults to 20 - final double customIconSize; - @override Widget build(BuildContext context) { - final theme = Zeta.of(context); - final colors = _getColors(theme); - return Container( - height: labelSize.height, - decoration: _buildDecoration(colors), - constraints: BoxConstraints(minWidth: labelSize.width), - child: _buildContent(colors, theme), - ); - } + final ZetaColorSwatch colors = status.colorSwatch(context); - BoxDecoration _buildDecoration(ZetaWidgetColor colors) { - return BoxDecoration( - color: colors.backgroundColor, - border: Border.all(color: colors.foregroundColor, width: borderWidth), - borderRadius: BorderRadius.circular(borderType == BorderType.rounded ? 10.0 : 0.0), - ); - } - - Widget _buildContent(ZetaWidgetColor colors, Zeta theme) { - return Padding( - padding: const EdgeInsets.fromLTRB(8, 2, 8, 2), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - _buildIcon(colors), - const SizedBox(width: Dimensions.xs), - Flexible( - child: Text( + return DecoratedBox( + decoration: BoxDecoration( + color: colors.shade10, + border: Border.all(color: colors.border), + borderRadius: rounded ? ZetaRadius.full : ZetaRadius.minimal, + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x2, vertical: ZetaSpacing.x1 / 2), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(customIcon ?? Icons.circle, size: ZetaSpacing.x2, color: colors.icon), + const SizedBox(width: ZetaSpacing.xs), + Text( label, - style: ZetaTextStyles.bodyMedium, + style: ZetaTextStyles.bodyMedium.apply(color: colors.shade10.onColor), overflow: TextOverflow.ellipsis, ), - ), - ], + ], + ), ), ); } - Icon _buildIcon(ZetaWidgetColor colors) { - final size = isDefaultIcon ? Dimensions.x2 : customIconSize; - return Icon( - size: size, - isDefaultIcon ? Icons.circle : (customIcon ?? Icons.star), - color: colors.foregroundColor, - ); - } - - ZetaWidgetColor _getColors(Zeta theme) { - final defaultColorScheme = ZetaWidgetColor( - backgroundColor: theme.colors.surfaceDisabled, - foregroundColor: theme.colors.borderDefault, - ); - switch (severity) { - case WidgetSeverity.neutral: - return defaultColorScheme; - case WidgetSeverity.info: - return ZetaWidgetColor( - backgroundColor: theme.colors.purple.shade10, - foregroundColor: theme.colors.purple.shade50, - ); - case WidgetSeverity.positive: - return ZetaWidgetColor( - backgroundColor: theme.colors.green.shade10, - foregroundColor: theme.colors.green.shade50, - ); - case WidgetSeverity.warning: - return ZetaWidgetColor( - backgroundColor: theme.colors.orange.shade10, - foregroundColor: theme.colors.orange.shade50, - ); - case WidgetSeverity.negative: - return ZetaWidgetColor( - backgroundColor: theme.colors.red.shade10, - foregroundColor: theme.colors.red.shade50, - ); - case WidgetSeverity.custom: - return customColors ?? defaultColorScheme; - } - } - @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(EnumProperty('borderType', borderType)) - ..add(DoubleProperty('borderWidth', borderWidth)) - ..add(DiagnosticsProperty('labelSize', labelSize)) - ..add(EnumProperty('severity', severity)) ..add(StringProperty('label', label)) - ..add( - DiagnosticsProperty( - 'customColors', - customColors, - ), - ) - ..add(DiagnosticsProperty('isDefaultIcon', isDefaultIcon)) + ..add(DiagnosticsProperty('rounded', rounded)) ..add(DiagnosticsProperty('customIcon', customIcon)) - ..add(DoubleProperty('customIconSize', customIconSize)); + ..add(EnumProperty('severity', status)); } } diff --git a/lib/src/components/badges/tag.dart b/lib/src/components/badges/tag.dart index d0c5d9a5..09367596 100644 --- a/lib/src/components/badges/tag.dart +++ b/lib/src/components/badges/tag.dart @@ -3,78 +3,92 @@ import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -///Tag Direction options +///Tag Direction options for [ZetaTag]. enum ZetaTagDirection { - ///facing left + ///Tag facing left. left, - ///facing right + ///Tag facing right. right } ///Zeta Tag class ZetaTag extends StatelessWidget { - ///Constructs [ZetaTag] + ///Constructs [ZetaTag]. const ZetaTag({ + super.key, this.direction = ZetaTagDirection.left, - this.borderType = BorderType.sharp, required this.label, - super.key, + this.rounded = true, }); - ///Constructor [ZetaTag] left sided + /// Constructs left facing [ZetaTag]. factory ZetaTag.left({ - BorderType borderType = BorderType.sharp, required String label, + bool rounded = true, }) => ZetaTag( - borderType: borderType, label: label, + rounded: rounded, ); - ///Constructor [ZetaTag] right sided + ///Constructs right facing [ZetaTag]. factory ZetaTag.right({ - BorderType borderType = BorderType.sharp, required String label, + bool rounded = true, }) => ZetaTag( direction: ZetaTagDirection.right, - borderType: borderType, + rounded: rounded, label: label, ); - /// Fixed container size - static const Size _containerSize = Size(36, 28); - ///Determines the direction of the tag /// /// Defaults to left final ZetaTagDirection direction; - ///Border type of the widget - ///Defaults to sharp - final BorderType borderType; + /// {@zeta-component-rounded} + final bool rounded; ///tag label final String label; + /// Fixed container size + static const Size _containerSize = Size(ZetaSpacing.x9, ZetaSpacing.x7); + @override Widget build(BuildContext context) { return Row( children: [ - if (direction == ZetaTagDirection.right) ...[ - _buildCustomPaint(context), - ], - _buildContainer(context), - if (direction == ZetaTagDirection.left) ...[ - _buildCustomPaint(context), - ], + if (direction == ZetaTagDirection.right) _buildCustomPaint(context), + Container( + decoration: BoxDecoration( + color: Zeta.of(context).colors.surfaceHovered, + borderRadius: _getBorderRadius(), + ), + height: _containerSize.height, + constraints: BoxConstraints(minWidth: _containerSize.width), + child: Center( + child: FittedBox( + child: Padding( + padding: const EdgeInsets.fromLTRB(ZetaSpacing.x2, 1, ZetaSpacing.x2, 1), + child: Text( + label, + style: ZetaTextStyles.bodyMedium, + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + ), + if (direction == ZetaTagDirection.left) _buildCustomPaint(context), ], ); } - BorderRadius _getBorderRadius() { - if (borderType == BorderType.sharp) return BorderRadius.zero; + BorderRadius? _getBorderRadius() { + if (!rounded) return null; if (direction == ZetaTagDirection.right) { return const BorderRadius.only( topRight: Radius.circular(2), @@ -88,60 +102,24 @@ class ZetaTag extends StatelessWidget { } } - Widget _buildContainer(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: _getWidgetColor(context), - borderRadius: _getBorderRadius(), - ), - height: _containerSize.height, - constraints: BoxConstraints(minWidth: _containerSize.width), - child: Center( - child: FittedBox( - child: Padding( - padding: const EdgeInsets.fromLTRB( - Dimensions.x2, - 1, - Dimensions.x2, - 1, - ), - child: Text( - label, - style: ZetaTextStyles.bodyMedium, - overflow: TextOverflow.ellipsis, - ), - ), - ), - ), - ); - } - Widget _buildCustomPaint(BuildContext context) { - return Stack( - children: [ - CustomPaint( - size: const Size(Dimensions.x3, Dimensions.x7), - painter: _TagPainter( - color: _getWidgetColor(context), - direction: direction, - borderType: borderType, - ), - ), - // Additional widgets if needed - ], + return CustomPaint( + size: const Size(ZetaSpacing.x3, ZetaSpacing.x7), + painter: _TagPainter( + color: Zeta.of(context).colors.surfaceHovered, + direction: direction, + rounded: rounded, + ), ); } - Color _getWidgetColor(BuildContext context) => - Zeta.of(context).themeMode == ThemeMode.dark ? ZetaColorBase.greyWarm.shade90 : ZetaColorBase.greyCool.shade30; - @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties ..add(EnumProperty('direction', direction)) - ..add(EnumProperty('borderType', borderType)) - ..add(StringProperty('label', label)); + ..add(StringProperty('label', label)) + ..add(DiagnosticsProperty('rounded', rounded)); } } @@ -149,55 +127,58 @@ class _TagPainter extends CustomPainter { const _TagPainter({ required this.color, required this.direction, - required this.borderType, + required this.rounded, }); final Color color; final ZetaTagDirection direction; - final BorderType borderType; + final bool rounded; @override void paint(Canvas canvas, Size size) { final Paint paint = Paint() ..color = color ..style = PaintingStyle.fill; - final path = _buildPath(size); - if (borderType != BorderType.sharp) _drawDot(canvas, size); - canvas.drawPath(path, paint); - } + final path = _drawPath(size, rounded, direction == ZetaTagDirection.right); - Path _buildPath(Size size) { - return direction == ZetaTagDirection.left ? _leftPath(size) : _rightPath(size); + canvas.drawPath(path, paint); } - void _drawDot(Canvas canvas, Size size) { - final paint = Paint()..color = color; - const double dotSize = 1.7; - - Offset dotPosition; - if (direction == ZetaTagDirection.right) { - dotPosition = Offset(2, size.height / 2); + Path _drawPath(Size size, bool rounded, bool isRight) { + /// Const points of path + const double a = 0.1; + const double b = 0.04; + const double c = 0.48; + const double d = 0.55; + + // Dynamic points on path + final double e = isRight ? size.width : 0; + final double f = isRight ? 1 : -1; + + final path = Path() + ..moveTo(e + f, 0) + ..lineTo(e, 0); + if (rounded) { + path + ..lineTo(size.width * (isRight ? a : 1 - a), size.height * (1 - d)) + ..cubicTo( + size.width * (isRight ? b : 1 - b), + size.height * c, + size.width * (isRight ? b : 1 - b), + size.height * (1 - c), + size.width * (isRight ? a : 1 - a), + size.height * d, + ); } else { - dotPosition = Offset(size.width - 2, size.height / 2); + path.lineTo(isRight ? 0 : size.width, size.height / 2); } - canvas.drawCircle(dotPosition, dotSize, paint); - } - - Path _leftPath(Size size) { - return Path() - ..moveTo(0, size.height) - ..lineTo(size.width, size.height / 2) - ..lineTo(0, 0) + path + ..lineTo(e, size.height) + ..lineTo(e + f, size.height) ..close(); - } - Path _rightPath(Size size) { - return Path() - ..moveTo(0, size.height / 2) - ..lineTo(size.width, 0) - ..lineTo(size.width, size.height) - ..close(); + return path; } @override diff --git a/lib/src/components/badges/workcloud_indicator.dart b/lib/src/components/badges/workcloud_indicator.dart index a5ceab54..3a79c04a 100644 --- a/lib/src/components/badges/workcloud_indicator.dart +++ b/lib/src/components/badges/workcloud_indicator.dart @@ -5,194 +5,152 @@ import '../../../zeta_flutter.dart'; ///Indicator Type enum ZetaWorkcloudIndicatorType { - ///sets the color to red - urgent, + /// Red. + one, - ///sets the color to orange - high, + /// Orange + two, - ///sets the color to blue - medium, + /// Blue. + three, - ///sets the color to green - low, + /// Green. + four, - ///sets the color to custom color - custom + /// Purple. + five, + + /// Pink. + six, + + /// Yellow. + seven, + + /// Teal + eight, + + /// Cool grey. + nine, + + /// Warn grey. + ten, +} + +extension on ZetaWorkcloudIndicatorType { + ZetaColorSwatch color(BuildContext context) { + final colors = Zeta.of(context).colors; + switch (this) { + case ZetaWorkcloudIndicatorType.one: + return colors.red; + case ZetaWorkcloudIndicatorType.two: + return colors.orange; + case ZetaWorkcloudIndicatorType.three: + return colors.blue; + case ZetaWorkcloudIndicatorType.four: + return colors.green; + case ZetaWorkcloudIndicatorType.five: + return colors.purple; + case ZetaWorkcloudIndicatorType.six: + return colors.pink; + case ZetaWorkcloudIndicatorType.seven: + return colors.yellow; + case ZetaWorkcloudIndicatorType.eight: + return colors.teal; + case ZetaWorkcloudIndicatorType.nine: + return colors.cool; + case ZetaWorkcloudIndicatorType.ten: + return colors.warm; + } + } } -///Zeta Workcloud Indicator +/// Zeta Workcloud Indicator. +/// +/// There are 10 available levels in which ether the values 1 through 10 can be used, +/// or icons can be passed. class ZetaWorkcloudIndicator extends StatelessWidget { ///Constructs [ZetaWorkcloudIndicator] const ZetaWorkcloudIndicator({ - this.isStatusBadge = true, - this.priorityType, + super.key, + this.priorityType = ZetaWorkcloudIndicatorType.one, this.prioritySize = ZetaWidgetSize.small, this.label, this.index, - this.customColors, - super.key, + this.icon, }); - ///Constructor for [ZetaWorkcloudIndicator] for type 'status' - factory ZetaWorkcloudIndicator.status({ - required String label, - }) => - ZetaWorkcloudIndicator(label: label); - - ///Constructor for [ZetaWorkcloudIndicator] for type 'priority pill' - factory ZetaWorkcloudIndicator.priorityPill({ - required String index, - ZetaWorkcloudIndicatorType priorityType = ZetaWorkcloudIndicatorType.urgent, - ZetaWidgetSize prioritySize = ZetaWidgetSize.small, - ZetaWidgetColor? customColors, - String? label, - }) => - ZetaWorkcloudIndicator( - isStatusBadge: false, - priorityType: priorityType, - prioritySize: prioritySize, - label: label, - index: index, - customColors: customColors, - ); - - ///Indicates if it is status badge or priority pill - /// - /// Defaults to status - final bool isStatusBadge; + /// The type of priority. + final ZetaWorkcloudIndicatorType priorityType; - ///The type of priority for Priority Pill + /// The size of Priority Pill. /// - ///[ZetaWorkcloudIndicator.priorityPill] defaults to 'urgent' - final ZetaWorkcloudIndicatorType? priorityType; - - ///The size of Priority Pill - /// - ///defaults to 'small' + /// Defaults to 'small'. final ZetaWidgetSize prioritySize; - ///Label + /// Text label. Not shown when [prioritySize] is [ZetaWidgetSize.small] final String? label; - ///Index for priority pill + /// Index value. Typically a number. /// - ///required for [ZetaWorkcloudIndicator.priorityPill] + /// If null, and no icon is provided, the index will match the [priorityType]. + /// + /// It is recommended to not exceed 2 characters here. final String? index; - ///Custom colors for priority pill - final ZetaWidgetColor? customColors; + /// Custom icon. If not null, this will replace the index text. + final IconData? icon; @override Widget build(BuildContext context) { - final theme = Zeta.of(context); - final themeMode = Zeta.of(context).themeMode; - return isStatusBadge ? _buildStatusBadge(theme) : _buildPriorityPill(theme, themeMode); - } - - ///Status Badge - Widget _buildStatusBadge(Zeta theme) { - final labelContent = label ?? ''; - return Container( - height: Dimensions.x6, - constraints: const BoxConstraints(minWidth: 51), - decoration: _statusBadgeDecoration(theme), - child: Center( - child: Padding( - padding: const EdgeInsets.fromLTRB( - Dimensions.x2, - Dimensions.x1, - Dimensions.x2, - Dimensions.x1, - ), - child: Text(labelContent, style: ZetaTextStyles.bodySmall), - ), - ), - ); - } - - BoxDecoration _statusBadgeDecoration(Zeta theme) { - return BoxDecoration( - color: theme.colors.surfaceDisabled, - borderRadius: BorderRadius.circular(6), - ); - } - - ///Priority Pill - Widget _buildPriorityPill(Zeta theme, ThemeMode themeMode) { - final colors = _ZetaWorkcloudIndicatorStyle.getColor( - priorityType ?? ZetaWorkcloudIndicatorType.urgent, - theme.colors, - themeMode, - customColors: customColors, - ); - final size = _ZetaWorkcloudIndicatorStyle.getSize(prioritySize); - final padding = _ZetaWorkcloudIndicatorStyle.getEdgeInsets(prioritySize); - final textStyle = _ZetaWorkcloudIndicatorStyle.getTextStyle(prioritySize, theme); + final ZetaColorSwatch color = priorityType.color(context); + final textStyle = prioritySize == ZetaWidgetSize.large ? ZetaTextStyles.labelMedium : ZetaTextStyles.labelTiny; return DecoratedBox( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(Dimensions.l), - color: colors.foregroundColor, + borderRadius: BorderRadius.circular(ZetaSpacing.l), + color: color.shade20, ), child: Row( mainAxisSize: MainAxisSize.min, children: [ - _buildPriorityPillIndex(size, colors, textStyle, theme), - if (prioritySize != ZetaWidgetSize.small) ...[ - _buildPriorityPillLabel(textStyle, padding), - ], + SizedBox.square( + dimension: prioritySize == ZetaWidgetSize.large ? ZetaSpacing.x6 : ZetaSpacing.x5, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: priorityType == ZetaWorkcloudIndicatorType.nine ? color.shade80 : color, + ), + child: Center( + child: icon != null + ? Icon( + icon, + size: prioritySize == ZetaWidgetSize.large ? ZetaSpacing.x4 : ZetaSpacing.x3_5, + color: color.onColor, + ) + : Text( + index ?? (priorityType.index + 1).toString(), + style: textStyle.apply(color: color.onColor), + textAlign: TextAlign.center, + ), + ), + ), + ), + if (prioritySize != ZetaWidgetSize.small) + Container( + constraints: const BoxConstraints(minWidth: ZetaSpacing.x9), + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.xs), + child: Text(label ?? '', style: textStyle, overflow: TextOverflow.ellipsis), + ), ], ), ); } - Widget _buildPriorityPillIndex( - double size, - ZetaWidgetColor colors, - TextStyle textStyle, - Zeta theme, - ) { - return Container( - alignment: Alignment.center, - height: size, - width: size, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: colors.backgroundColor, - ), - child: Center( - child: Text( - index ?? '', - style: textStyle.apply(color: theme.colors.white), - textAlign: TextAlign.center, - ), - ), - ); - } - - Widget _buildPriorityPillLabel( - TextStyle textStyle, - EdgeInsets padding, - ) { - return Container( - constraints: const BoxConstraints(minWidth: 34), - child: Padding( - padding: padding, - child: Text( - label ?? '', - style: textStyle, - overflow: TextOverflow.ellipsis, - ), - ), - ); - } - @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(DiagnosticsProperty('isStatusBadge', isStatusBadge)) ..add( EnumProperty('priorityType', priorityType), ) @@ -201,73 +159,6 @@ class ZetaWorkcloudIndicator extends StatelessWidget { ) ..add(StringProperty('label', label)) ..add(StringProperty('index', index)) - ..add( - DiagnosticsProperty('customColors', customColors), - ); - } -} - -class _ZetaIndicatorConstants { - static const double mediumSize = 22; - static const double largeSize = 24; - static const EdgeInsets largePadding = EdgeInsets.fromLTRB(8, 0, 8, 1); - static const EdgeInsets mediumPadding = EdgeInsets.fromLTRB(8, 2, 8, 2); -} - -class _ZetaWorkcloudIndicatorStyle { - static ZetaWidgetColor getColor( - ZetaWorkcloudIndicatorType type, - ZetaColors zetaColors, - ThemeMode themeMode, { - ZetaWidgetColor? customColors, - }) { - final isDarkTheme = themeMode == ThemeMode.dark; - switch (type) { - case ZetaWorkcloudIndicatorType.urgent: - return ZetaWidgetColor( - backgroundColor: isDarkTheme ? ZetaColorBase.red.shade70 : ZetaColorBase.red.shade60, - foregroundColor: isDarkTheme ? ZetaColorBase.red.shade90 : ZetaColorBase.red.shade20, - ); - case ZetaWorkcloudIndicatorType.high: - return ZetaWidgetColor( - backgroundColor: isDarkTheme ? ZetaColorBase.orange.shade70 : ZetaColorBase.orange.shade40, - foregroundColor: isDarkTheme ? ZetaColorBase.orange.shade90 : ZetaColorBase.orange.shade10, - ); - case ZetaWorkcloudIndicatorType.medium: - return ZetaWidgetColor( - backgroundColor: isDarkTheme ? ZetaColorBase.blue.shade70 : ZetaColorBase.blue, - foregroundColor: isDarkTheme ? ZetaColorBase.blue.shade90 : ZetaColorBase.blue.shade20, - ); - case ZetaWorkcloudIndicatorType.low: - return ZetaWidgetColor( - backgroundColor: isDarkTheme ? ZetaColorBase.green.shade70 : ZetaColorBase.green.shade60, - foregroundColor: isDarkTheme ? ZetaColorBase.green.shade90 : ZetaColorBase.green.shade20, - ); - case ZetaWorkcloudIndicatorType.custom: - return customColors ?? - ZetaWidgetColor( - backgroundColor: zetaColors.surfaceDisabled, - foregroundColor: zetaColors.surfacePrimary, - ); - } - } - - static double getSize(ZetaWidgetSize size) { - if (size == ZetaWidgetSize.large) { - return _ZetaIndicatorConstants.largeSize; - } - return _ZetaIndicatorConstants.mediumSize; - } - - static TextStyle getTextStyle(ZetaWidgetSize size, Zeta theme) { - if (size == ZetaWidgetSize.large) return ZetaTextStyles.bodyMedium; - return ZetaTextStyles.bodySmall; - } - - static EdgeInsets getEdgeInsets(ZetaWidgetSize size) { - if (size == ZetaWidgetSize.large) { - return _ZetaIndicatorConstants.largePadding; - } - return _ZetaIndicatorConstants.mediumPadding; + ..add(DiagnosticsProperty('icon', icon)); } } diff --git a/lib/src/components/banners/in_page_banner.dart b/lib/src/components/banners/in_page_banner.dart index e96e2052..f5b955ea 100644 --- a/lib/src/components/banners/in_page_banner.dart +++ b/lib/src/components/banners/in_page_banner.dart @@ -3,45 +3,30 @@ import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -///[ZetaInPageBanner] button attributes -class ZetaPageBannerButton { - ///Constructs [ZetaPageBannerButton] - const ZetaPageBannerButton({this.onPressed, this.label}); - - ///Called when the button is tapped. - final VoidCallback? onPressed; - - ///Label for the button - final String? label; -} - ///Zeta In Page Banner class ZetaInPageBanner extends StatelessWidget { ///Constructs [ZetaInPageBanner] const ZetaInPageBanner({ + super.key, required this.content, - this.borderType = BorderType.rounded, - this.severity = WidgetSeverity.info, + this.rounded = true, + this.severity = ZetaWidgetStatus.info, this.showIconClose = true, this.onClose, this.title, - this.customColors, this.customIcon, - this.firstButton, - this.secondButton, - super.key, + this.actions = const [], }); ///The content of the banner final Widget content; - ///The border type of the banner - ///Defaults to 'rounded' - final BorderType borderType; + /// {@macro zeta-component-rounded} + final bool rounded; ///Determines the color of the banner ///Defaults to 'neutral' - final WidgetSeverity severity; + final ZetaWidgetStatus severity; ///Determines if the banner has icon for closing ///Defaults to true @@ -50,19 +35,11 @@ class ZetaInPageBanner extends StatelessWidget { ///Title of the banner final String? title; - ///If [severity] is set to 'custom', - /// - ///[customColors] should be set. - final ZetaWidgetColor? customColors; - ///Custom icon final IconData? customIcon; - ///Attributes for the left button - final ZetaPageBannerButton? firstButton; - - ///Attributes for the right button - final ZetaPageBannerButton? secondButton; + /// Action buttons to show at the bottom of the banner. + final List actions; ///Called when the button 'Close' is tapped. final VoidCallback? onClose; @@ -71,194 +48,94 @@ class ZetaInPageBanner extends StatelessWidget { Widget build(BuildContext context) { final theme = Zeta.of(context); final colors = _getColors(theme); - return DecoratedBox( - decoration: _buildDecoration(colors), - child: Padding( - padding: const EdgeInsets.all(Dimensions.x3), - child: Column( - children: _buildBannerContent(theme, colors), - ), - ), - ); - } - - List _buildBannerContent(Zeta theme, ZetaWidgetColor colors) { final hasTitle = title != null; - return [ - if (hasTitle) _buildTitleRow(colors, theme), - _buildContentRow(theme, colors, hasTitle), - ]; - } - Widget _buildTitleRow(ZetaWidgetColor colors, Zeta theme) { - return Padding( - padding: const EdgeInsets.only(bottom: Dimensions.x2), - child: Row( - children: [ - Expanded( - child: Row( - children: [ - _buildIconLeft(colors, theme), - const SizedBox(width: Dimensions.x2), - if (title != null) ...[_buildTitle()], - ], - ), - ), - if (showIconClose) ...[ - Align( - alignment: Alignment.centerRight, - child: _buildIconClose(), - ), - ], - ], + return DecoratedBox( + decoration: BoxDecoration( + color: colors.backgroundColor, + border: Border.all(color: colors.foregroundColor), + borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, ), - ); - } - - Widget _buildContentRow(Zeta theme, ZetaWidgetColor colors, bool hasTitle) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + child: Padding( + padding: const EdgeInsets.all(2), + child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (title == null) ...[ - _buildIconLeft(colors, theme), - const SizedBox(width: Dimensions.x2), - ], - _buildContent(hasTitle, theme), - if (showIconClose && !hasTitle) ...[_buildIconClose()], - ], - ), - _buildButtonsRow(theme, colors), - ], - ); - } - - Widget _buildButtonsRow(Zeta theme, ZetaWidgetColor colors) { - return Row( - children: [ - const Padding(padding: EdgeInsets.only(left: Dimensions.x7)), - if (firstButton != null) ...[ - _buildButton(theme, colors, firstButton!), - const SizedBox(width: Dimensions.x2), - ], - if (secondButton != null) ...[ - _buildButton(theme, colors, secondButton!), - ], - ], - ); - } - - BoxDecoration _buildDecoration(ZetaWidgetColor colors) { - return BoxDecoration( - color: colors.backgroundColor, - border: Border.all(color: colors.foregroundColor), - borderRadius: BorderRadius.circular( - borderType == BorderType.rounded ? Dimensions.x1 : Dimensions.x0, - ), - ); - } - - Expanded _buildContent(bool hasTitle, Zeta theme) => Expanded( - child: Padding( - padding: EdgeInsets.only(left: hasTitle ? Dimensions.x7 : Dimensions.x0), - child: DefaultTextStyle( - style: ZetaTextStyles.bodyMedium.apply(color: theme.colors.textDefault), - child: content, - ), - ), - ); - - Widget _buildIconClose() => GestureDetector( - onTap: onClose, - child: Icon( - borderType == BorderType.sharp ? ZetaIcons.close_sharp : ZetaIcons.close_round, - size: Dimensions.x5, - ), - ); - - Icon _buildIconLeft(ZetaWidgetColor colors, Zeta theme) => Icon( - _getIconLeft(), - size: Dimensions.x5, - color: severity == WidgetSeverity.neutral ? theme.colors.textDefault : colors.foregroundColor, - ); - - Widget _buildTitle() => Flexible( - child: Text( - title!, - style: ZetaTextStyles.titleSmall, - softWrap: true, - overflow: TextOverflow.ellipsis, - ), - ); - - Widget _buildButton( - Zeta theme, - ZetaWidgetColor colors, - ZetaPageBannerButton buttonAttributes, - ) { - return Padding( - padding: const EdgeInsets.only(top: Dimensions.x3), - child: ZetaButton.outlined( - label: buttonAttributes.label ?? '', - borderType: borderType, - size: ZetaWidgetSize.medium, - colors: ZetaButtonColors( - borderColor: theme.colors.borderSubtle, - foregroundColor: theme.colors.textDefault, - actionColor: ZetaColorBase.greyCool.shade30, + Padding( + padding: const EdgeInsetsDirectional.only(top: 12, start: 10), + child: Icon( + severity.icon(rounded: rounded), + size: ZetaSpacing.x5, + color: severity == ZetaWidgetStatus.neutral ? theme.colors.textDefault : colors.foregroundColor, + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + if (hasTitle) + Text( + title!, + style: ZetaTextStyles.titleSmall, + ).paddingBottom(ZetaSpacing.xxs), + DefaultTextStyle( + style: ZetaTextStyles.bodyMedium.apply(color: theme.colors.textDefault), + child: content, + ), + if (actions.isNotEmpty) + Row( + children: actions + .map((e) => e.copyWith(size: ZetaWidgetSize.medium, type: ZetaButtonType.outlineSubtle)) + .divide(const SizedBox.square(dimension: ZetaSpacing.x2)) + .toList(), + ).paddingTop(ZetaSpacing.x4), + const SizedBox(height: 10), + ], + ), + ), + if (showIconClose) + IconButton( + onPressed: onClose, + icon: Icon( + !rounded ? ZetaIcons.close_sharp : ZetaIcons.close_round, + size: ZetaSpacing.x5, + ), + ), + ].divide(const SizedBox.square(dimension: ZetaSpacing.x2)).toList(), ), - onPressed: buttonAttributes.onPressed, ), ); } - IconData _getIconLeft() { - final isRounded = borderType == BorderType.rounded; - final defaultIcon = isRounded ? ZetaIcons.info_round : ZetaIcons.info_sharp; - if (severity == WidgetSeverity.positive) { - return isRounded ? ZetaIcons.check_circle_round : ZetaIcons.check_circle_sharp; - } else if (severity == WidgetSeverity.warning) { - return isRounded ? ZetaIcons.warning_round : ZetaIcons.warning_sharp; - } else if (severity == WidgetSeverity.negative) { - return isRounded ? ZetaIcons.error_round : ZetaIcons.error_sharp; - } else if (severity == WidgetSeverity.custom) { - return customIcon ?? defaultIcon; - } - return defaultIcon; - } - ZetaWidgetColor _getColors(Zeta theme) { final defaultColorScheme = ZetaWidgetColor( backgroundColor: theme.colors.surfacePrimary, foregroundColor: theme.colors.borderDefault, ); switch (severity) { - case WidgetSeverity.neutral: + case ZetaWidgetStatus.neutral: return defaultColorScheme; - case WidgetSeverity.info: + case ZetaWidgetStatus.info: return ZetaWidgetColor( backgroundColor: theme.colors.info.surface, foregroundColor: theme.colors.info.border, ); - case WidgetSeverity.positive: + case ZetaWidgetStatus.positive: return ZetaWidgetColor( backgroundColor: theme.colors.positive.surface, foregroundColor: theme.colors.positive.border, ); - case WidgetSeverity.warning: + case ZetaWidgetStatus.warning: return ZetaWidgetColor( backgroundColor: theme.colors.warning.surface.lighten(6), foregroundColor: theme.colors.warning.border, ); - case WidgetSeverity.negative: + case ZetaWidgetStatus.negative: return ZetaWidgetColor( backgroundColor: theme.colors.negative.surface, foregroundColor: theme.colors.negative.border, ); - case WidgetSeverity.custom: - return customColors ?? defaultColorScheme; } } @@ -266,28 +143,32 @@ class ZetaInPageBanner extends StatelessWidget { void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(EnumProperty('borderType', borderType)) - ..add(EnumProperty('severity', severity)) - ..add(DiagnosticsProperty('isClosing', showIconClose)) - ..add(StringProperty('title', title)) - ..add( - DiagnosticsProperty('customColors', customColors), - ) - ..add(DiagnosticsProperty('customIcon', customIcon)) - ..add( - DiagnosticsProperty('firstButton', firstButton), - ) - ..add( - DiagnosticsProperty( - 'secondButton', - secondButton, - ), - ) ..add( ObjectFlagProperty.has( 'onCloseFunction', onClose, ), - ); + ) + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(EnumProperty('severity', severity)) + ..add(DiagnosticsProperty('showIconClose', showIconClose)) + ..add(StringProperty('title', title)) + ..add(DiagnosticsProperty('customIcon', customIcon)); + } +} + +extension on ZetaWidgetStatus { + IconData icon({required bool rounded}) { + switch (this) { + case ZetaWidgetStatus.positive: + return rounded ? ZetaIcons.check_circle_round : ZetaIcons.check_circle_sharp; + case ZetaWidgetStatus.warning: + return rounded ? ZetaIcons.warning_round : ZetaIcons.warning_sharp; + case ZetaWidgetStatus.negative: + return rounded ? ZetaIcons.error_round : ZetaIcons.error_sharp; + case ZetaWidgetStatus.neutral: + case ZetaWidgetStatus.info: + return rounded ? ZetaIcons.info_round : ZetaIcons.info_sharp; + } } } diff --git a/lib/src/components/banners/system_banner.dart b/lib/src/components/banners/system_banner.dart index f41c95b6..6648e49e 100644 --- a/lib/src/components/banners/system_banner.dart +++ b/lib/src/components/banners/system_banner.dart @@ -1,156 +1,100 @@ -import 'package:flutter/foundation.dart'; +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../../zeta_flutter.dart'; /// [ZetaSystemBanner] type -enum ZetaSystemBannerType { - /// blue background - defaultAppBar, +enum ZetaSystemBannerStatus { + /// Primary background. + primary, - /// green background - positiveAppBar, + /// Green background. + positive, - /// brown/yellow background - warningAppBar, + /// Yellow background. + warning, - /// red background - negativeAppBar, + /// Red background. + negative, } -/// ZetaSystemBanner component -class ZetaSystemBanner extends StatelessWidget implements PreferredSizeWidget { - /// Constructor for [ZetaSystemBanner] - const ZetaSystemBanner({ +/// ZetaSystemBanner. Extends [MaterialBanner]. +/// +/// A banner displays an important, succinct message, and provides action for users to address. +/// It draws the attention to the message by displaying it at the top in various colors. +class ZetaSystemBanner extends MaterialBanner { + /// Constructor for [ZetaSystemBanner]. See [MaterialBanner] for more information. + ZetaSystemBanner({ + required BuildContext context, + required String title, super.key, - this.type = ZetaSystemBannerType.defaultAppBar, - this.leading, - this.centerTitle = false, - this.actions, - this.title, - this.titleIcon, - this.titleSpacing, - this.systemOverlayStyle, - this.automaticallyImplyLeading = false, - }); - - /// The type of the [ZetaSystemBanner] - final ZetaSystemBannerType type; - - /// AppBar leading - final Widget? leading; - - /// AppBar title - final Widget? title; - - /// Icon to place next to the AppBar title, on the left side. - final Icon? titleIcon; - - /// AppBar centerTitle - final bool centerTitle; - - /// AppBar titleSpacing - final double? titleSpacing; - - /// AppBar automaticallyImplyLeading. Default is `true` - final bool automaticallyImplyLeading; - - /// AppBar actions - final List? actions; - - /// AppBar systemOverlayStyle - final SystemUiOverlayStyle? systemOverlayStyle; - - @override - Widget build(BuildContext context) { - final foregroundColor = _foregroundColorFromType(context, type); - return AppBar( - titleSpacing: titleSpacing, - centerTitle: centerTitle, - backgroundColor: _backgroundColorFromType(context, type), - foregroundColor: foregroundColor, - systemOverlayStyle: systemOverlayStyle ?? - SystemUiOverlayStyle.dark.copyWith( - statusBarIconBrightness: _statusBarIconBrightness(context, type), + IconData? leadingIcon, + ZetaSystemBannerStatus type = ZetaSystemBannerStatus.primary, + bool titleStart = false, + Widget? trailing, + }) : super( + content: Builder( + builder: (context) { + final backgroundColor = _backgroundColorFromType(context, type); + final foregroundColor = backgroundColor.onColor; + if (context.mounted) { + // ignore: invalid_use_of_visible_for_testing_member + if (Platform.isAndroid && SystemChrome.latestStyle?.statusBarColor != backgroundColor) { + SystemChrome.setSystemUIOverlayStyle( + SystemUiOverlayStyle( + statusBarColor: backgroundColor, + systemNavigationBarIconBrightness: backgroundColor.isDark ? Brightness.light : Brightness.dark, + ), + ); + } + } + + return DefaultTextStyle( + style: ZetaTextStyles.titleSmall.copyWith( + color: foregroundColor, + overflow: TextOverflow.ellipsis, + height: 1, + ), + child: Row( + mainAxisAlignment: titleStart ? MainAxisAlignment.center : MainAxisAlignment.start, + children: [ + if (leadingIcon != null) + Padding( + padding: const EdgeInsets.only(right: ZetaSpacing.x2), + child: Icon( + leadingIcon, + color: foregroundColor, + size: ZetaSpacing.x6, + ), + ), + Flexible(child: Text(title)), + ], + ), + ); + }, ), - leading: leading, - automaticallyImplyLeading: automaticallyImplyLeading, - title: DefaultTextStyle( - style: ZetaTextStyles.titleSmall.apply(color: foregroundColor, overflow: TextOverflow.ellipsis), - child: titleIcon == null - ? title ?? const SizedBox() - : Row( - mainAxisAlignment: centerTitle ? MainAxisAlignment.center : MainAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.only(right: title == null ? 0 : 8), - child: titleIcon, - ), - Flexible( - child: title ?? const SizedBox(), - ), - ], - ), - ), - actions: actions ?? (leading != null && titleIcon != null ? [const SizedBox(width: 40)] : null), - ); - } + backgroundColor: _backgroundColorFromType(context, type), + actions: [ + IconTheme( + data: IconThemeData(color: _backgroundColorFromType(context, type).onColor), + child: trailing ?? const SizedBox(), + ), + ], + ); + + static ZetaColorSwatch _backgroundColorFromType(BuildContext context, ZetaSystemBannerStatus type) { + final zeta = Zeta.of(context); - Color _backgroundColorFromType(BuildContext context, ZetaSystemBannerType type) { - final themeMode = Zeta.of(context).themeMode; switch (type) { - case ZetaSystemBannerType.defaultAppBar: - return ZetaColorBase.blue.shade60; - case ZetaSystemBannerType.positiveAppBar: - return themeMode == ThemeMode.dark ? ZetaColorBase.green.shade70 : ZetaColorBase.green; - case ZetaSystemBannerType.warningAppBar: - return themeMode == ThemeMode.dark ? ZetaColorBase.orange.shade30 : ZetaColorBase.orange.shade60; - case ZetaSystemBannerType.negativeAppBar: - return ZetaColorBase.red.shade60; + case ZetaSystemBannerStatus.primary: + return zeta.colors.primary; + case ZetaSystemBannerStatus.positive: + return zeta.colors.positive; + case ZetaSystemBannerStatus.warning: + return zeta.colors.orange; + case ZetaSystemBannerStatus.negative: + return zeta.colors.negative; } } - - Color _foregroundColorFromType(BuildContext context, ZetaSystemBannerType type) { - switch (type) { - case ZetaSystemBannerType.defaultAppBar: - return ZetaColorBase.white; - case ZetaSystemBannerType.positiveAppBar: - return ZetaColorBase.white; - case ZetaSystemBannerType.warningAppBar: - return ZetaColorBase.black; - case ZetaSystemBannerType.negativeAppBar: - return ZetaColorBase.white; - } - } - - Brightness _statusBarIconBrightness(BuildContext context, ZetaSystemBannerType type) { - switch (type) { - case ZetaSystemBannerType.defaultAppBar: - return Brightness.light; - case ZetaSystemBannerType.positiveAppBar: - return Brightness.light; - case ZetaSystemBannerType.warningAppBar: - return Brightness.dark; - case ZetaSystemBannerType.negativeAppBar: - return Brightness.light; - } - } - - @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight); - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', type)) - ..add(DiagnosticsProperty('leading', leading)) - ..add(DiagnosticsProperty('title', title)) - ..add(DiagnosticsProperty('titleIcon', titleIcon)) - ..add(DiagnosticsProperty('centerTitle', centerTitle)) - ..add(DiagnosticsProperty('titleSpacing', titleSpacing)) - ..add(DiagnosticsProperty('automaticallyImplyLeading', automaticallyImplyLeading)) - ..add(DiagnosticsProperty?>('actions', actions)) - ..add(DiagnosticsProperty('systemOverlayStyle', systemOverlayStyle)); - } } diff --git a/lib/src/components/buttons/button.dart b/lib/src/components/buttons/button.dart index 8b0dd8a6..3395ad6c 100644 --- a/lib/src/components/buttons/button.dart +++ b/lib/src/components/buttons/button.dart @@ -3,43 +3,71 @@ import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -///Colors for the [ZetaButton] widget -class ZetaButtonColors extends ZetaWidgetColor { - ///Construct [ZetaButtonColors] - const ZetaButtonColors({ - this.actionColor, - this.backgroundDisabled = ZetaColorBase.greyCool, - this.foregroundDisabled = ZetaColorBase.greyWarm, - this.borderColor = Colors.transparent, - this.iconColor, - super.backgroundColor = Colors.transparent, - super.foregroundColor = Colors.black12, - }); +///Button types +enum ZetaButtonType { + /// Background: Primary color; defaults to blue. + /// Border: None. + primary, - ///Defines the color used when the Button is pressed - final Color? actionColor; + /// Background: Secondary color; defaults to yellow. + /// Border: None. + secondary, - ///The color for the border when the [ZetaButton] is of type 'outlined' - final Color borderColor; + /// Background: Positive color; defaults to green. + /// Border: None. + positive, - ///The color for the icon - ///If color is not set, default color will be [foregroundColor] - final Color? iconColor; + /// Background: Negative color; defaults to red. + /// Border: None. + negative, - ///Color for the [ZetaButton] when it is disabled - final Color backgroundDisabled; + /// Background: None. + /// Border: Primary color; defaults to blue. + outline, - ///Color for the [ZetaButton] icon and text when it is disabled - final Color foregroundDisabled; + /// Background: None. + /// Border: Subtle color; defaults to cool grey. + outlineSubtle, + + /// Background: None. + /// Border: None. + /// Foreground color: Primary; defaults to blue. + text, } -///Button types -enum ZetaButtonType { - ///Standard button with background color - filled, +extension on ZetaButtonType { + ZetaColorSwatch color(ZetaColors colors) { + switch (this) { + case ZetaButtonType.secondary: + return colors.secondary; + case ZetaButtonType.positive: + return colors.positive; + case ZetaButtonType.negative: + return colors.negative; + case ZetaButtonType.outline: + case ZetaButtonType.primary: + return colors.primary; + case ZetaButtonType.outlineSubtle: + case ZetaButtonType.text: + return colors.cool; + } + } - ///Button with border - outlined, + bool get border => this == ZetaButtonType.outline || this == ZetaButtonType.outlineSubtle; + bool get solid => index < 4; +} + +extension on BorderType { + BorderRadius get radius { + switch (this) { + case BorderType.sharp: + return ZetaRadius.none; + case BorderType.rounded: + return ZetaRadius.minimal; + case BorderType.full: + return ZetaRadius.full; + } + } } ///Zeta Button @@ -47,182 +75,218 @@ class ZetaButton extends StatelessWidget { ///Constructs [ZetaButton] const ZetaButton({ required this.label, - required this.colors, - this.icon, this.onPressed, - this.iconOnRight = false, - this.type = ZetaButtonType.filled, - this.size = ZetaWidgetSize.large, + this.type = ZetaButtonType.primary, + this.size = ZetaWidgetSize.medium, this.borderType = BorderType.rounded, super.key, }); - ///Constructor for [ZetaButton] for type 'filled' - factory ZetaButton.filled({ - required String label, - required ZetaButtonColors colors, - IconData? icon, - VoidCallback? onPressed, - bool iconOnRight = false, - ZetaWidgetSize size = ZetaWidgetSize.small, - BorderType borderType = BorderType.rounded, - }) => - ZetaButton( - label: label, - icon: icon, - onPressed: onPressed, - iconOnRight: iconOnRight, - size: size, - colors: colors, - borderType: borderType, - ); - - ///Constructor for [ZetaButton] for type 'outlined' - factory ZetaButton.outlined({ - required String label, - required ZetaButtonColors colors, - IconData? icon, - VoidCallback? onPressed, - bool iconOnRight = false, - ZetaWidgetSize size = ZetaWidgetSize.small, - BorderType borderType = BorderType.rounded, - }) => - ZetaButton( - label: label, - icon: icon, - onPressed: onPressed, - iconOnRight: iconOnRight, - size: size, - colors: colors, - borderType: borderType, - type: ZetaButtonType.outlined, - ); + /// Constructs [ZetaButton] with Primary theme. + const ZetaButton.primary({ + required this.label, + this.onPressed, + this.size = ZetaWidgetSize.medium, + this.borderType = BorderType.rounded, + super.key, + }) : type = ZetaButtonType.primary; + + /// Constructs [ZetaButton] with Secondary theme. + const ZetaButton.secondary({ + required this.label, + this.onPressed, + this.size = ZetaWidgetSize.medium, + this.borderType = BorderType.rounded, + super.key, + }) : type = ZetaButtonType.secondary; + + /// Constructs [ZetaButton] with Positive theme. + const ZetaButton.positive({ + required this.label, + this.onPressed, + this.size = ZetaWidgetSize.medium, + this.borderType = BorderType.rounded, + super.key, + }) : type = ZetaButtonType.positive; + + /// Constructs [ZetaButton] with Negative theme. + const ZetaButton.negative({ + required this.label, + this.onPressed, + this.size = ZetaWidgetSize.medium, + this.borderType = BorderType.rounded, + super.key, + }) : type = ZetaButtonType.negative; + + /// Constructs [ZetaButton] with Outline theme. + const ZetaButton.outline({ + required this.label, + this.onPressed, + this.size = ZetaWidgetSize.medium, + this.borderType = BorderType.rounded, + super.key, + }) : type = ZetaButtonType.outline; + + /// Constructs [ZetaButton] with Outline Subtle theme. + const ZetaButton.outlineSubtle({ + required this.label, + this.onPressed, + this.size = ZetaWidgetSize.medium, + this.borderType = BorderType.rounded, + super.key, + }) : type = ZetaButtonType.outlineSubtle; + + /// Constructs [ZetaButton] with text theme. + const ZetaButton.text({ + required this.label, + this.onPressed, + this.size = ZetaWidgetSize.medium, + this.borderType = BorderType.rounded, + super.key, + }) : type = ZetaButtonType.text; ///Button label final String label; - ///The icon for the button - final IconData? icon; - ///Called when the button is tapped or otherwise activated. final VoidCallback? onPressed; - ///Determines if the icon should be on the left or right side - ///Defaults to 'false' (Left icon) - final bool iconOnRight; - ///The coloring type of the button final ZetaButtonType type; - ///Colors for the button - final ZetaButtonColors colors; - ///Whether or not the button is sharp or rounded ///Defaults to rounded final BorderType borderType; - ///Size of the button - ///Defaults to large + /// Size of the button. Defaults to large. final ZetaWidgetSize size; - @override - Widget build(BuildContext context) { - return ElevatedButton( - onPressed: onPressed, - style: _buttonStyle(), - child: _buildButtonContent(), + /// Creates a clone + ZetaButton copyWith({ + String? label, + VoidCallback? onPressed, + ZetaButtonType? type, + ZetaWidgetSize? size, + BorderType? borderType, + Key? key, + }) { + return ZetaButton( + label: label ?? this.label, + onPressed: onPressed ?? this.onPressed, + type: type ?? this.type, + size: size ?? this.size, + borderType: borderType ?? this.borderType, + key: key ?? this.key, ); } - Widget _buildButtonContent() { - List children = []; - if (icon != null) { - children - ..add(_buildIcon()) - ..add(const SizedBox(width: Dimensions.x2)); - } - children.add(_buildLabel()); - if (iconOnRight) children = children.reversed.toList(); - return IntrinsicWidth( - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: children, + @override + Widget build(BuildContext context) { + final colors = Zeta.of(context).colors; + return ConstrainedBox( + constraints: BoxConstraints(minHeight: _minConstraints, minWidth: _minConstraints), + child: FilledButton( + onPressed: onPressed, + style: _buttonStyle(colors), + child: SelectionContainer.disabled( + child: label.isEmpty + ? const SizedBox() + : Text( + label, + style: _textStyle, + ).paddingHorizontal(_textPadding), + ), ), ); } - Widget _buildLabel() => Text(label, style: _getTextStyle()); - - Widget _buildIcon() => Transform.translate( - offset: const Offset(0, -1), - child: Icon( - icon, - color: onPressed != null ? (colors.iconColor ?? colors.foregroundColor) : colors.foregroundDisabled, - size: _iconSize(), - ), - ); - - ButtonStyle _buttonStyle() { - return ElevatedButton.styleFrom( - minimumSize: _getButtonSize(), - elevation: 0, - padding: _buttonPadding(), - shape: RoundedRectangleBorder(borderRadius: _getBorderRadius()), - ).copyWith( + ButtonStyle _buttonStyle(ZetaColors colors) { + return ButtonStyle( + minimumSize: MaterialStateProperty.all(const Size.square(32)), + shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: borderType.radius)), backgroundColor: MaterialStateProperty.resolveWith( (states) { if (states.contains(MaterialState.disabled)) { - return colors.backgroundDisabled; + return colors.surfaceDisabled; + } + if (states.contains(MaterialState.pressed)) { + return type.solid ? type.color(colors).shade70 : colors.primary.shade10; + } + if (states.contains(MaterialState.hovered)) { + return type.solid ? type.color(colors).shade50 : colors.cool.shade20; } - return colors.backgroundColor; + return type.solid ? type.color(colors) : Colors.transparent; }, ), foregroundColor: MaterialStateProperty.resolveWith( (states) { if (states.contains(MaterialState.disabled)) { - return colors.foregroundDisabled; + return colors.textDisabled; + } + switch (type) { + case ZetaButtonType.outline: + case ZetaButtonType.text: + return colors.primary; + case ZetaButtonType.outlineSubtle: + return colors.textDefault; + case ZetaButtonType.primary: + case ZetaButtonType.secondary: + case ZetaButtonType.positive: + case ZetaButtonType.negative: + return type.color(colors).onColor; } - return colors.foregroundColor; }, ), overlayColor: MaterialStateProperty.resolveWith((Set states) { - if (states.contains(MaterialState.pressed)) return colors.actionColor; return null; }), side: MaterialStateProperty.resolveWith((Set states) { - if (type == ZetaButtonType.filled) return null; - if (states.contains(MaterialState.disabled)) { - return BorderSide(color: colors.foregroundDisabled); + if (type.border) { + if (states.contains(MaterialState.disabled)) { + return BorderSide(color: colors.cool.shade40); + } + + return BorderSide(color: type == ZetaButtonType.outline ? colors.primary.border : colors.borderDefault); } - return BorderSide(color: colors.borderColor); + + // TODO(thelukewalton): This removes a defualt border when focused, rather than adding a second border when focused. + if (states.contains(MaterialState.focused)) { + return BorderSide(color: colors.blue, width: 2); + } + return null; }), + elevation: const MaterialStatePropertyAll(0), + padding: MaterialStateProperty.all(EdgeInsets.zero), ); } - BorderRadius _getBorderRadius() => - borderType == BorderType.rounded ? BorderRadius.circular(Dimensions.x1) : BorderRadius.zero; + // TODO(thelukewalton): Check styles for pressed etc. + TextStyle get _textStyle => size == ZetaWidgetSize.small ? ZetaTextStyles.labelMedium : ZetaTextStyles.labelLarge; - TextStyle _getTextStyle() => size == ZetaWidgetSize.small ? ZetaTextStyles.labelMedium : ZetaTextStyles.labelLarge; + double get _minConstraints { + switch (size) { + case ZetaWidgetSize.large: + return ZetaSpacing.x12; - double _iconSize() => size == ZetaWidgetSize.small ? Dimensions.x4 : Dimensions.x5; + case ZetaWidgetSize.medium: + return ZetaSpacing.x10; - EdgeInsets _buttonPadding() { - if (size == ZetaWidgetSize.small) { - return const EdgeInsets.fromLTRB(10, 6, 10, 6); - } else if (size == ZetaWidgetSize.medium) { - return const EdgeInsets.fromLTRB(14, 8, 14, 8); + case ZetaWidgetSize.small: + return ZetaSpacing.x8; } - return const EdgeInsets.fromLTRB(20, 12, 20, 12); } - Size _getButtonSize() { - if (size == ZetaWidgetSize.small) { - return const Size(68, 32); - } else if (size == ZetaWidgetSize.medium) { - return const Size(82, 40); + double get _textPadding { + switch (size) { + case ZetaWidgetSize.large: + return ZetaSpacing.m; + + case ZetaWidgetSize.medium: + return ZetaSpacing.x3_5; + + case ZetaWidgetSize.small: + return 10; } - return const Size(98, 48); } @override @@ -230,10 +294,7 @@ class ZetaButton extends StatelessWidget { super.debugFillProperties(properties); properties ..add(StringProperty('label', label)) - ..add(DiagnosticsProperty('icon', icon)) ..add(ObjectFlagProperty.has('onPressed', onPressed)) - ..add(DiagnosticsProperty('iconOnRight', iconOnRight)) - ..add(DiagnosticsProperty('colors', colors)) ..add(EnumProperty('type', type)) ..add(EnumProperty('borderType', borderType)) ..add(EnumProperty('size', size)); diff --git a/lib/src/components/buttons/fab.dart b/lib/src/components/buttons/fab.dart index 61f14792..c39c052d 100644 --- a/lib/src/components/buttons/fab.dart +++ b/lib/src/components/buttons/fab.dart @@ -170,7 +170,7 @@ class _ZetaFABState extends State { mainAxisSize: MainAxisSize.min, children: [ Icon(widget.buttonIcon, size: iconSize), - const SizedBox(width: Dimensions.x2), + const SizedBox(width: ZetaSpacing.x2), Text(widget.buttonLabel, style: textStyle), ], ), @@ -203,23 +203,23 @@ class _ZetaFABState extends State { BorderRadius _getBorderRadius() => widget.buttonShape == ZetaFabShape.rounded ? BorderRadius.circular( - widget.buttonSize == ZetaFabSize.small ? Dimensions.x2 : Dimensions.x4, + widget.buttonSize == ZetaFabSize.small ? ZetaSpacing.x2 : ZetaSpacing.x4, ) : BorderRadius.zero; BorderRadius _getBorderRadiusExtended() => widget.buttonShape == ZetaFabShape.circle ? BorderRadius.circular( - widget.buttonSize == ZetaFabSize.small ? Dimensions.x7 : Dimensions.x12, + widget.buttonSize == ZetaFabSize.small ? ZetaSpacing.x7 : ZetaSpacing.x12, ) : widget.buttonShape == ZetaFabShape.rounded - ? BorderRadius.circular(Dimensions.x2) + ? BorderRadius.circular(ZetaSpacing.x2) : BorderRadius.zero; TextStyle _getTextStyle() => ZetaTextStyles.labelLarge; - double _getButtonSize() => widget.buttonSize == ZetaFabSize.small ? Dimensions.x14 : Dimensions.x24; + double _getButtonSize() => widget.buttonSize == ZetaFabSize.small ? ZetaSpacing.x14 : ZetaSpacing.x24; - double _getIconSize() => widget.buttonSize == ZetaFabSize.small ? Dimensions.x6 : Dimensions.x9; + double _getIconSize() => widget.buttonSize == ZetaFabSize.small ? ZetaSpacing.x6 : ZetaSpacing.x9; EdgeInsets _getPadding() => !_isExpanded ? EdgeInsets.zero diff --git a/lib/src/components/checkbox/checkbox.dart b/lib/src/components/checkbox/checkbox.dart index b0acd201..45b4d41f 100644 --- a/lib/src/components/checkbox/checkbox.dart +++ b/lib/src/components/checkbox/checkbox.dart @@ -10,7 +10,7 @@ class ZetaCheckbox extends StatelessWidget { required this.onChanged, this.borderType = BorderType.sharp, this.label, - this.checkboxSize = const Size(20, 20), + this.checkboxSize = const Size(ZetaSpacing.x5, ZetaSpacing.x5), this.selectedColor, this.unselectedColor, this.unselectedBorderColor, @@ -101,7 +101,7 @@ class ZetaCheckbox extends StatelessWidget { if (label != null) ...[ Flexible( child: Padding( - padding: const EdgeInsets.only(left: Dimensions.s), + padding: const EdgeInsets.only(left: ZetaSpacing.s), child: Text(label!, style: ZetaTextStyles.bodyLarge), ), ), diff --git a/lib/src/components/chip/chip.dart b/lib/src/components/chip/chip.dart index 80bde652..05084561 100644 --- a/lib/src/components/chip/chip.dart +++ b/lib/src/components/chip/chip.dart @@ -93,7 +93,7 @@ class ZetaChip extends StatelessWidget { @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - final avatarSize = type == ZetaChipType.input ? 24.0 : 20.0; + final avatarSize = type == ZetaChipType.input ? ZetaSpacing.x6 : ZetaSpacing.x5; final bgColor = type == ZetaChipType.status ? colors.warm.shade30 : selected diff --git a/lib/src/components/password/password_input.dart b/lib/src/components/password/password_input.dart index 33b81778..32e029ef 100644 --- a/lib/src/components/password/password_input.dart +++ b/lib/src/components/password/password_input.dart @@ -137,7 +137,7 @@ class _ZetaPasswordInputState extends State { Widget _buildLabel() { return Padding( - padding: const EdgeInsets.symmetric(vertical: Dimensions.x1), + padding: const EdgeInsets.symmetric(vertical: ZetaSpacing.x1), child: Text(widget.label!, style: ZetaTextStyles.bodyMedium), ); } @@ -164,7 +164,7 @@ class _ZetaPasswordInputState extends State { return OutlineInputBorder( borderSide: BorderSide(color: color, width: width), borderRadius: BorderRadius.circular( - widget.borderType == BorderType.rounded ? Dimensions.x1 : Dimensions.x0, + widget.borderType == BorderType.rounded ? ZetaSpacing.x1 : ZetaSpacing.x0, ), ); } @@ -193,17 +193,17 @@ class _ZetaPasswordInputState extends State { Widget _buildFooter(_ZetaPasswordInputColors colors) { return Padding( - padding: const EdgeInsets.only(top: Dimensions.x1), + padding: const EdgeInsets.only(top: ZetaSpacing.x1), child: Row( children: [ if (_errorMessage != null) ..._buildError(colors.borderErrorColor), if (_errorMessage == null && widget.footerIcon != null) ...[ Icon( widget.footerIcon, - size: Dimensions.x4, + size: ZetaSpacing.x4, color: widget.enabled ? colors.hintIconColor : colors.hintIconDisableColor, ), - const SizedBox(width: Dimensions.x1), + const SizedBox(width: ZetaSpacing.x1), ], if (_errorMessage == null && widget.footerText != null) ...[ Text( @@ -222,10 +222,10 @@ class _ZetaPasswordInputState extends State { return [ Icon( ZetaIcons.error_round, - size: Dimensions.x4, + size: ZetaSpacing.x4, color: color, ), - const SizedBox(width: Dimensions.x1), + const SizedBox(width: ZetaSpacing.x1), Text( _errorMessage!, style: ZetaTextStyles.bodySmall.apply(color: color), @@ -238,7 +238,7 @@ class _ZetaPasswordInputState extends State { valueListenable: _obscureTextNotifier, builder: (context, value, child) { return IconButton( - padding: const EdgeInsets.symmetric(vertical: Dimensions.x1), + padding: const EdgeInsets.symmetric(vertical: ZetaSpacing.x1), icon: Icon( value ? ZetaIcons.visibility_off_sharp : ZetaIcons.visibility_sharp, size: _getSuffixIconSize(), @@ -259,11 +259,11 @@ class _ZetaPasswordInputState extends State { double _getInputHeight() { switch (widget.size) { case ZetaWidgetSize.small: - return Dimensions.x8; + return ZetaSpacing.x8; case ZetaWidgetSize.medium: - return Dimensions.x10; + return ZetaSpacing.x10; case ZetaWidgetSize.large: - return Dimensions.x12; + return ZetaSpacing.x12; } } @@ -273,8 +273,8 @@ class _ZetaPasswordInputState extends State { } double _getSuffixIconSize() { - if (widget.size == ZetaWidgetSize.small) return Dimensions.x4; - return Dimensions.x5; + if (widget.size == ZetaWidgetSize.small) return ZetaSpacing.x4; + return ZetaSpacing.x5; } } diff --git a/lib/src/theme/colors.dart b/lib/src/theme/colors.dart index 9abdc4f3..bdab7cb4 100644 --- a/lib/src/theme/colors.dart +++ b/lib/src/theme/colors.dart @@ -30,7 +30,7 @@ class ZetaColors { Color? surfaceTertiary, bool adjust = true, }) : primary = _adjustedValue(primary, ZetaColorBase.blue, adjust, brightness, contrast), - secondary = _adjustedValue(secondary, primary ?? ZetaColorBase.blue, adjust, brightness, contrast), + secondary = _adjustedValue(secondary, primary ?? ZetaColorBase.yellow, adjust, brightness, contrast), error = _adjustedValue(error, ZetaColorBase.red, adjust, brightness, contrast), cool = _adjustedValue(cool, ZetaColorBase.greyCool, adjust, brightness, ZetaContrast.aa), warm = _adjustedValue(warm, ZetaColorBase.greyWarm, adjust, brightness, ZetaContrast.aa), @@ -169,7 +169,7 @@ class ZetaColors { /// Secondary color used in app. /// - /// Defaults to `ZetaColors.cool.90`. + /// Defaults to [ZetaColorBase.yellow] /// /// Maps to [ColorScheme.secondary]. final ZetaColorSwatch secondary; @@ -252,11 +252,11 @@ class ZetaColors { /// {@macro zeta-color-dark} Color get textInverse => cool.shade20; - /// {@template zeta-color-dark} /// Default icon color. /// /// Defaults to `ZetaColors.cool.90`. /// + /// {@template zeta-color-dark} /// Color swatches are inverted if [ZetaColors.brightness] is Dark. /// {@endtemplate} Color get iconDefault => textDefault; @@ -316,6 +316,9 @@ class ZetaColors { /// {@macro zeta-color-dark} Color get borderSelected => cool.shade90; + /// True if current [ZetaColors] object uses dark mode colors. + bool get isDarkMode => brightness == Brightness.dark; + // Links /// Link color. @@ -340,7 +343,6 @@ class ZetaColors { /// Secondary surface color. /// - /// /// * `ZetaColors.cool.10`. final Color surfaceSecondary; diff --git a/lib/src/theme/tokens.dart b/lib/src/theme/tokens.dart index c3c0fe56..93e534bf 100644 --- a/lib/src/theme/tokens.dart +++ b/lib/src/theme/tokens.dart @@ -1,9 +1,11 @@ +import 'package:flutter/material.dart'; + /// Tokens that are used for spacing. /// /// Values are doubles, and can be used for padding, margins and other spacings. /// // TODO(thelukewalton): Refactor to match latest designs. -class Dimensions { +class ZetaSpacing { /// Base multiplier used to calculate spacing values. static const double spacingBaseMultiplier = 4; @@ -91,3 +93,21 @@ class Dimensions { /// 96dp space. static const double xxxl = spacingBaseMultiplier * 24; } + +/// Tokens used for Border Radius. +class ZetaRadius { + /// No border radius; 0px radius. + static const BorderRadius none = BorderRadius.zero; + + /// Smallest amount of border radius; 4px radius. + static const BorderRadius minimal = BorderRadius.all(Radius.circular(ZetaSpacing.xxs)); + + /// Border radius used when rounded parameter is true; 8px radius. + static const BorderRadius rounded = BorderRadius.all(Radius.circular(ZetaSpacing.xs)); + + /// Wide border radius; 24px radius. + static const BorderRadius wide = BorderRadius.all(Radius.circular(ZetaSpacing.m)); + + /// Largest amount of border radius; 360px radius. + static const BorderRadius full = BorderRadius.all(Radius.circular(360)); +} diff --git a/lib/src/utils/enums.dart b/lib/src/utils/enums.dart index d183631f..1979b2c6 100644 --- a/lib/src/utils/enums.dart +++ b/lib/src/utils/enums.dart @@ -1,12 +1,16 @@ import 'dart:ui'; +import '../../zeta_flutter.dart'; ///Border Types enum BorderType { - ///sharp border + /// Sharp border sharp, - ///rounded border + /// Slightly rounded border. rounded, + + /// Fully rounded border. + full, } /// Widget Severity @@ -56,3 +60,21 @@ class ZetaWidgetColor { ///foregroundColor Color final Color foregroundColor; } + +/// Status options for [ZetaBadge], [ZetaStatusLabel], [ZetaInPageBanner]. +enum ZetaWidgetStatus { + /// Information widget; defaults to purple color scheme. + info, + + /// Positive widget; defaults to green color scheme. + positive, + + /// Warning widget; defaults to yellow color scheme. + warning, + + /// Negative widget; defaults to red color scheme. + negative, + + /// Neutral widget; defaults to grey color scheme. + neutral, +} diff --git a/lib/src/utils/extensions.dart b/lib/src/utils/extensions.dart index f78f72eb..352b744b 100644 --- a/lib/src/utils/extensions.dart +++ b/lib/src/utils/extensions.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import '../../zeta_flutter.dart'; + /// Extension to add dividers to any view that can take an iterable. /// /// Iterable can be converted to a list with [toList]. @@ -46,3 +48,34 @@ extension SpacingWidget on Widget { /// Equal padding on start and end. Widget paddingHorizontal(double space) => Padding(padding: EdgeInsets.symmetric(horizontal: space), child: this); } + +/// Extensions on [num]. +extension NumExtensions on num? { + /// Returns input as a formatted string with a maximum amount of characters. + /// + /// [maxChars] defaults to one. + String formatMaxChars([int maxChars = 1]) { + final strVal = this == null ? '' : this!.abs().toString(); + return strVal.length > maxChars ? '${'9' * maxChars}+' : strVal; + } +} + +/// Extensions on [ZetaWidgetStatus]. +extension ColorSwatches on ZetaWidgetStatus { + /// Gets color swatch from [ZetaWidgetStatus] + ZetaColorSwatch colorSwatch(BuildContext context) { + final colors = Zeta.of(context).colors; + switch (this) { + case ZetaWidgetStatus.info: + return colors.info; + case ZetaWidgetStatus.positive: + return colors.positive; + case ZetaWidgetStatus.warning: + return colors.warning; + case ZetaWidgetStatus.negative: + return colors.negative; + case ZetaWidgetStatus.neutral: + return colors.cool; + } + } +} diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000..61d4398e --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,7 @@ +{ + "packages": { + ".": { + "release-type": "dart" + } + } +} \ No newline at end of file From 45468f9eec9f27579d434f1190cb5bd6d20d59f1 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Fri, 2 Feb 2024 10:29:49 +0000 Subject: [PATCH 35/41] chore: UX-918 part 2. Refactor components (#56) - [x] Accordion - [x] Avatar - [x] Badges - [x] Banners - [x] Bottom Sheets - [x] Buttons - [x] FABs - [x] Checkbox - [x] Chip - [x] Password Input --- .release-please-manifest.json | 3 + LICENSE | 2 +- custom_docs/components/Grid/flutter.md | 59 - custom_docs/components/Spacing/flutter.md | 198 -- custom_docs/components/Typography/flutter.md | 98 - example/lib/home.dart | 2 +- example/lib/pages/assets/icons_example.dart | 1984 ++++++++--------- .../pages/components/accordion_example.dart | 157 +- .../lib/pages/components/avatar_example.dart | 1013 +++++---- .../lib/pages/components/badges_example.dart | 22 +- .../lib/pages/components/banner_example.dart | 20 +- .../lib/pages/components/bottom_sheet.dart | 97 - .../components/bottom_sheet_example.dart | 83 + .../lib/pages/components/button_example.dart | 104 +- .../pages/components/checkbox_example.dart | 44 +- .../lib/pages/components/chip_example.dart | 389 ++-- .../components/password_input_example.dart | 24 +- example/macos/Podfile.lock | 18 +- .../macos/Runner.xcodeproj/project.pbxproj | 1 - example/pubspec.lock | 34 +- example/pubspec.yaml | 1 + example/test/checkbox_test.dart | 38 +- example/test/fab_test.dart | 6 +- example/test/in_page_banner_test.dart | 3 +- example/test/test_components.dart | 27 +- .../components/accordion_widgetbook.dart | 31 +- .../components/avatar_widgetbook.dart | 57 +- .../components/badges_widgetbook.dart | 2 +- .../components/banner_widgetbook.dart | 4 +- .../components/bottom_sheet_widgetbook.dart | 10 +- .../components/button_widgetbook.dart | 14 +- .../components/checkbox_widgetbook.dart | 5 +- .../components/chip_widgetbook.dart | 77 +- .../components/password_input_widgetbook.dart | 2 +- lib/src/assets/icons.dart | 4 - lib/src/components/accordion/accordion.dart | 233 +- lib/src/components/avatars/avatar.dart | 465 ++-- lib/src/components/badges/badge.dart | 2 +- lib/src/components/badges/indicator.dart | 114 +- lib/src/components/badges/status_label.dart | 4 +- lib/src/components/badges/tag.dart | 27 +- .../components/banners/in_page_banner.dart | 78 +- .../bottom sheets/bottom_sheet.dart | 67 +- .../components/bottom sheets/menu_items.dart | 152 +- lib/src/components/buttons/button.dart | 50 +- lib/src/components/buttons/fab.dart | 276 +-- lib/src/components/checkbox/checkbox.dart | 320 +-- lib/src/components/chip/chip.dart | 252 --- lib/src/components/chips/assist_chip.dart | 14 + lib/src/components/chips/chip.dart | 177 ++ lib/src/components/chips/filter_chip.dart | 14 + lib/src/components/chips/input_chip.dart | 15 + .../components/password/password_input.dart | 269 +-- lib/src/theme/tokens.dart | 10 +- lib/src/utils/enums.dart | 43 +- lib/src/utils/extensions.dart | 16 + lib/zeta_flutter.dart | 2 +- pubspec.yaml | 5 - zeta-icons-other.json | 1 - 59 files changed, 3224 insertions(+), 4015 deletions(-) create mode 100644 .release-please-manifest.json delete mode 100644 custom_docs/components/Grid/flutter.md delete mode 100644 custom_docs/components/Spacing/flutter.md delete mode 100644 custom_docs/components/Typography/flutter.md delete mode 100644 example/lib/pages/components/bottom_sheet.dart create mode 100644 example/lib/pages/components/bottom_sheet_example.dart delete mode 100644 lib/src/components/chip/chip.dart create mode 100644 lib/src/components/chips/assist_chip.dart create mode 100644 lib/src/components/chips/chip.dart create mode 100644 lib/src/components/chips/filter_chip.dart create mode 100644 lib/src/components/chips/input_chip.dart delete mode 100644 zeta-icons-other.json diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000..2d50e200 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.1.1+23" +} \ No newline at end of file diff --git a/LICENSE b/LICENSE index c091ab8d..d4f367ee 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2023 Zebra Technologies +Copyright 2024 Zebra Technologies 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: diff --git a/custom_docs/components/Grid/flutter.md b/custom_docs/components/Grid/flutter.md deleted file mode 100644 index 0edc52d2..00000000 --- a/custom_docs/components/Grid/flutter.md +++ /dev/null @@ -1,59 +0,0 @@ -## ZetaGrid Usage - -To import ZetaGrid into a Dart file: - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -``` - -### Example - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -class ZetaGridExample extends StatelessWidget{ - const ZetaGridExample({Key? key}) : super(key: key); - @override - Widget build(BuildContext context) { - return ZetaGrid(...); - } -} -``` - -### Setup - -To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: - -```dart -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; -class MyApp extends StatelessWidget { - const MyApp({super.key}); - @override - Widget build(BuildContext context) { - return MaterialApp( - theme: ZetaTheme.zeta, - builder: (context, child) => ..., - ); - } -} -``` - -or - -```dart -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; -class MyApp extends StatelessWidget { - const MyApp({super.key}); - @override - Widget build(BuildContext context) { - return Theme( - data: ZetaTheme.zeta, - child: CupertinoApp( - builder: (context, child) => ..., - ), - ); - } -} -``` diff --git a/custom_docs/components/Spacing/flutter.md b/custom_docs/components/Spacing/flutter.md deleted file mode 100644 index 6eddb8b6..00000000 --- a/custom_docs/components/Spacing/flutter.md +++ /dev/null @@ -1,198 +0,0 @@ -## ZetaSpacing Usage - -To import ZetaSpacing into a Dart file: - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -``` - -### Example - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; - -class ZetaSpacingExample extends StatelessWidget{ - const ZetaSpacingExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ZetaSpacing(...); - } -} -``` - -### Setup - -To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: - -```dart -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - theme: ZetaTheme.zeta, - builder: (context, child) => ..., - ); - } -} -``` - -or - -```dart - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return Theme( - data: ZetaTheme.zeta, - child: CupertinoApp( - builder: (context, child) => ..., - ), - ); - } -} -``` - -### ZetaSpacing - -ZetaSpacing provides four options for spacing - -- `square` - applies inset to all 4 sides equally. -- `squish` - applies inset to top and bottom only. -- `inline` - applies inset to start and end only. -- `inlineStart` - applies inset to start only. For LTR locales this is the left, for RTL locales this is the right. -- `inlineEnd` - applies inset to end only. For LTR locales this is the right, for RTL locales this is the left. -- `stack` - applies inset to bottom only. - -These spacings should be applied with the following doubles: - -- `x0` - 0 -- `x1` - 4 - also `xxs` -- `x2` - 8 - also `xs` -- `x3` - 12 - also `s` -- `x4` - 16 - also `b` -- `x5` - 20 -- `x6` - 24 - also `m` -- `x7` - 28 -- `x8` - 32 - also `l` -- `x9` - 36 -- `x10` - 40 -- `x11` - 44 -- `x12` - 48 -- `x13` - 52 -- `x14` - 58 -- `x16` - 64 - also `xl` -- `x20` - 80 - also `xxl` -- `x24` - 96 - also `xxxl` - -Spacing components can be used in multiple ways: - -### ZetaSpacing() widget with named constructors. - -```dart -const ZetaSpacing.square( - Text('Example'), - size: Dimensions.x1, -), -const ZetaSpacing.squish( - Text('Example'), - size: Dimensions.x1, -), -const ZetaSpacing.stack( - Text('Example'), - size: Dimensions.x1, -) -const ZetaSpacing.inline( - Text('Example'), - size: Dimensions.x1, -) -``` - -This is the preferred way to use ZetaSpacing. Having a const, named constructor makes the intuitive and efficient. - -- Const constructor -- Can wrap any Widget. -- Padding inset around widget. - -
    - -### ZetaSpacing() widget. - -```dart -const ZetaSpacing( - Text('Example'), - size: Dimensions.x1, - type: ZetaSpacingType.square, -), -const ZetaSpacing( - Text('Example'), - size: Dimensions.x1, - type: ZetaSpacingType.squish, -), -const ZetaSpacing( - Text('Example'), - size: Dimensions.x1, - type: ZetaSpacingType.stack, -), -const ZetaSpacing( - Text('Example'), - size: Dimensions.x1, - type: ZetaSpacingType.inline, -), -``` - -This method is less intuitive than using the named constructor, although it does still provide a const constructor for efficiency. - -- Having a const constructor makes this a preferred approach to spacing. -- Can wrap any Widget. -- Padding inset around widget. - -
    - -### SpacingSize extension on double. - -```dart -Container( - padding: Dimensions.x1.square, - margin: Dimensions.x10.squish, - child: Text('Example'), -), -Container( - padding: Dimensions.x1.stack, - margin: Dimensions.x10.inline, - child: Text('Example'), -), -``` - -- Should be used with defined sizes: x0, x1,... or xxs, xs,... (although can be used on any double). -- Can be used for either padding or margin. -- Can be wrapped around any Widget, or used as a parameter. - -
    - -### SpacingWidget extension on Widget. - -```dart -Text('Example').square(Dimensions.x1), -Text('Example').squish(Dimensions.x1), -Text('Example').stack(Dimensions.x1), -Text('Example').inline(Dimensions.x1), -Text('Example').inlineStart(Dimensions.x1), -Text('Example').inlineEnd(Dimensions.x1), -``` - -- Should be used with defined sizes: x0, x1,... or xxs, xs,... (although can be used on any double). -- Padding inset around widget. -- Can be applied to any widget. diff --git a/custom_docs/components/Typography/flutter.md b/custom_docs/components/Typography/flutter.md deleted file mode 100644 index 3bd74554..00000000 --- a/custom_docs/components/Typography/flutter.md +++ /dev/null @@ -1,98 +0,0 @@ -## ZetaText Usage - -To import ZetaText into a Dart file: - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -``` - -### Example - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; - -class ZetaTextExample extends StatelessWidget{ - const ZetaTextExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ZetaText(...); - } -} -``` - -### Setup - -To ensure all components work as intended, applications should have ZetaTheme.zeta applied at their top level; typically within MaterialApp or wrapping its equivalent: - -```dart -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return MaterialApp( - theme: ZetaTheme.zeta, - builder: (context, child) => ..., - ); - } -} -``` - -or - -```dart - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/src/theme/theme.dart'; - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - @override - Widget build(BuildContext context) { - return Theme( - data: ZetaTheme.zeta, - child: CupertinoApp( - builder: (context, child) => ..., - ), - ); - } -} -``` - -### ZetaText - -Zeta text styles are within ZetaTheme.zeta, and so will be automatically applied to many widgets that use the built in text theme. When building components, text should not have any spacing by default, and so it is recommended to use the individual text styles with Text, rather than using ZetaText as this will by default apply a x2 squish padding (top and bottom). - -Zeta Typography styles can be used in multiple ways: - -### ZetaText widget with named constructors - -```dart -const ZetaText.bodySmall('Example'), -const ZetaText.displayLarge('Example'), -``` - -This is the preferred way to display text. Having a const, named constructor with helper parameters makes the intuitive and efficient. Constructors exist for all pre-defined text styles and helper functions exist to support all tokens. - -### ZetaText widget - -```dart -const ZetaText('Example', style: ZetaText.zetaBodySmall) -``` - -This method is less intuitive than using the named constructor, although it does still provide a const constructor for efficiency. Having a const, named constructor with helper functions makes the intuitive and efficient. Constructors exist for all pre-defined text styles and helper parameters exist to support all tokens. - -### ZetaText styles - -```dart -Text('Example', style: ZetaText.zetaBodySmall) -Text('Example', style: Theme.of(context).bodySmall) -``` - -Using the base styles gives the greatest flexibility as styles can be extended or added to where needed, at the expense of following the specifications exactly. As ZetaText.textTheme is within the base app style, we can use context to get the styles. This greatly speed up the process of applying Zeta to a pre-existing application. Using this method means helper parameters (such as caps) can not be used and spacing is not applied. This can be useful in components where spacing should be zero. diff --git a/example/lib/home.dart b/example/lib/home.dart index 7a1fd347..659ca5f7 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -4,7 +4,7 @@ import 'package:zeta_example/pages/components/accordion_example.dart'; import 'package:zeta_example/pages/components/avatar_example.dart'; import 'package:zeta_example/pages/components/badges_example.dart'; import 'package:zeta_example/pages/components/banner_example.dart'; -import 'package:zeta_example/pages/components/bottom_sheet.dart'; +import 'package:zeta_example/pages/components/bottom_sheet_example.dart'; import 'package:zeta_example/pages/components/button_example.dart'; import 'package:zeta_example/pages/components/checkbox_example.dart'; import 'package:zeta_example/pages/components/chip_example.dart'; diff --git a/example/lib/pages/assets/icons_example.dart b/example/lib/pages/assets/icons_example.dart index 079558cc..21d2c56d 100644 --- a/example/lib/pages/assets/icons_example.dart +++ b/example/lib/pages/assets/icons_example.dart @@ -17,1003 +17,999 @@ class _IconsExampleState extends State { @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: IconsExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(ZetaSpacing.s), - child: Column( + return ExampleScaffold( + name: IconsExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(ZetaSpacing.s), + child: Column( + children: [ + Text('Round', style: ZetaTextStyles.bodyLarge), + Wrap( + spacing: 8, + runSpacing: 8, children: [ - Text('Round', style: ZetaTextStyles.bodyLarge), - Wrap( - spacing: 8, - runSpacing: 8, - children: [ - // round - Icon(ZetaIcons.alarm_round), - Icon(ZetaIcons.ar_round), - Icon(ZetaIcons.bookmark_outline_round), - Icon(ZetaIcons.bookmark_round), - Icon(ZetaIcons.build_round), - Icon(ZetaIcons.cached_round), - Icon(ZetaIcons.calendar_3_day_round), - Icon(ZetaIcons.calendar_alt_1_round), - Icon(ZetaIcons.calendar_alt_2_round), - Icon(ZetaIcons.calendar_available_round), - Icon(ZetaIcons.calendar_cancel_round), - Icon(ZetaIcons.calendar_day_round), - Icon(ZetaIcons.calendar_edit_round), - Icon(ZetaIcons.calendar_monthly_alt_round), - Icon(ZetaIcons.calendar_monthly_round), - Icon(ZetaIcons.calendar_range_round), - Icon(ZetaIcons.calendar_round), - Icon(ZetaIcons.calendar_weekly_alt_round), - Icon(ZetaIcons.calendar_weekly_round), - Icon(ZetaIcons.calendar_yearly_round), - Icon(ZetaIcons.check_circle_outline_alt_round), - Icon(ZetaIcons.check_circle_outline_round), - Icon(ZetaIcons.check_circle_round), - Icon(ZetaIcons.check_mark_round), - Icon(ZetaIcons.clipboard_round), - Icon(ZetaIcons.clock_outline_round), - Icon(ZetaIcons.clock_round), - Icon(ZetaIcons.credit_card_round), - Icon(ZetaIcons.delete_forever_round), - Icon(ZetaIcons.delete_outline_round), - Icon(ZetaIcons.delete_round), - Icon(ZetaIcons.dislike_action_round), - Icon(ZetaIcons.document_round), - Icon(ZetaIcons.download_round), - Icon(ZetaIcons.filter_alt_round), - Icon(ZetaIcons.filter_round), - Icon(ZetaIcons.hand_round), - Icon(ZetaIcons.history_round), - Icon(ZetaIcons.home_round), - Icon(ZetaIcons.info_round), - Icon(ZetaIcons.label_round), - Icon(ZetaIcons.like_action_round), - Icon(ZetaIcons.lock_alt_round), - Icon(ZetaIcons.lock_round), - Icon(ZetaIcons.log_in_round), - Icon(ZetaIcons.log_out_round), - Icon(ZetaIcons.love_outline_round), - Icon(ZetaIcons.love_round), - Icon(ZetaIcons.open_in_full_round), - Icon(ZetaIcons.open_in_new_window_round), - Icon(ZetaIcons.pending_round), - Icon(ZetaIcons.pin_round), - Icon(ZetaIcons.price_round), - Icon(ZetaIcons.renew_round), - Icon(ZetaIcons.search_round), - Icon(ZetaIcons.security_check_round), - Icon(ZetaIcons.settings_round), - Icon(ZetaIcons.sync_action_round), - Icon(ZetaIcons.touch_round), - Icon(ZetaIcons.trending_down_round), - Icon(ZetaIcons.trending_up_round), - Icon(ZetaIcons.unlock_alt_round), - Icon(ZetaIcons.unlock_round), - Icon(ZetaIcons.update_round), - Icon(ZetaIcons.upload_round), - Icon(ZetaIcons.user_circle_round), - Icon(ZetaIcons.user_round), - Icon(ZetaIcons.user_settings_round), - Icon(ZetaIcons.verified_round), - Icon(ZetaIcons.visibility_off_round), - Icon(ZetaIcons.visibility_round), - Icon(ZetaIcons.world_action_round), - Icon(ZetaIcons.zoom_in_round), - Icon(ZetaIcons.zoom_out_round), - Icon(ZetaIcons.add_alert_round), - Icon(ZetaIcons.alert_round), - Icon(ZetaIcons.auto_delete_round), - Icon(ZetaIcons.error_outline_round), - Icon(ZetaIcons.error_round), - Icon(ZetaIcons.important_notification_round), - Icon(ZetaIcons.warning_outline_round), - Icon(ZetaIcons.warning_round), - Icon(ZetaIcons.block_round), - Icon(ZetaIcons.closed_caption_round), - Icon(ZetaIcons.fast_forward_round), - Icon(ZetaIcons.fast_rewind_round), - Icon(ZetaIcons.loop_round), - Icon(ZetaIcons.microphone_off_round), - Icon(ZetaIcons.microphone_outline_round), - Icon(ZetaIcons.microphone_round), - Icon(ZetaIcons.pause_circle_round), - Icon(ZetaIcons.pause_round), - Icon(ZetaIcons.play_circle_round), - Icon(ZetaIcons.play_outline_round), - Icon(ZetaIcons.play_round), - Icon(ZetaIcons.replay_round), - Icon(ZetaIcons.skip_next_round), - Icon(ZetaIcons.skip_previous_round), - Icon(ZetaIcons.stop_circle_round), - Icon(ZetaIcons.stop_round), - Icon(ZetaIcons.video_camera_round), - Icon(ZetaIcons.volume_down_round), - Icon(ZetaIcons.volume_mute_round), - Icon(ZetaIcons.volume_off_round), - Icon(ZetaIcons.volume_up_round), - Icon(ZetaIcons.add_call_round), - Icon(ZetaIcons.chat_bubble_outline_round), - Icon(ZetaIcons.chat_bubble_round), - Icon(ZetaIcons.conversation_round), - Icon(ZetaIcons.dialpad_round), - Icon(ZetaIcons.do_not_disturb_round), - Icon(ZetaIcons.dollar_round), - Icon(ZetaIcons.email_alt_round), - Icon(ZetaIcons.email_outline_round), - Icon(ZetaIcons.email_round), - Icon(ZetaIcons.end_call_round), - Icon(ZetaIcons.message_round), - Icon(ZetaIcons.person_search_round), - Icon(ZetaIcons.phone_bluetooth_speaker_round), - Icon(ZetaIcons.phone_in_talk_round), - Icon(ZetaIcons.phone_round), - Icon(ZetaIcons.priority_round), - Icon(ZetaIcons.qr_code_round), - Icon(ZetaIcons.qr_code_scan_round), - Icon(ZetaIcons.rss_feed_round), - Icon(ZetaIcons.sd_card_round), - Icon(ZetaIcons.sim_card_round), - Icon(ZetaIcons.sms_round), - Icon(ZetaIcons.sync_disabled_round), - Icon(ZetaIcons.sync_round), - Icon(ZetaIcons.add_box_round), - Icon(ZetaIcons.add_circle_outline_round), - Icon(ZetaIcons.add_circle_round), - Icon(ZetaIcons.add_round), - Icon(ZetaIcons.analysis_round), - Icon(ZetaIcons.android_round), - Icon(ZetaIcons.backspace_round), - Icon(ZetaIcons.block_content_round), - Icon(ZetaIcons.clear_round), - Icon(ZetaIcons.content_round), - Icon(ZetaIcons.copy_file_round), - Icon(ZetaIcons.create_round), - Icon(ZetaIcons.filter_list_round), - Icon(ZetaIcons.flag_round), - Icon(ZetaIcons.link_content_round), - Icon(ZetaIcons.mail_round), - Icon(ZetaIcons.push_pin_round), - Icon(ZetaIcons.redo_round), - Icon(ZetaIcons.remove_box_round), - Icon(ZetaIcons.remove_circle_outline_round), - Icon(ZetaIcons.remove_circle_round), - Icon(ZetaIcons.remove_round), - Icon(ZetaIcons.reply_round), - Icon(ZetaIcons.save_alt_round), - Icon(ZetaIcons.save_round), - Icon(ZetaIcons.send_round), - Icon(ZetaIcons.sort_round), - Icon(ZetaIcons.undo_round), - Icon(ZetaIcons.antenna_round), - Icon(ZetaIcons.battery_alert_round), - Icon(ZetaIcons.battery_charging_round), - Icon(ZetaIcons.battery_round), - Icon(ZetaIcons.bluetooth_disabled_round), - Icon(ZetaIcons.bluetooth_round), - Icon(ZetaIcons.bluetooth_searching_round), - Icon(ZetaIcons.brightness_round), - Icon(ZetaIcons.cellular_signal_round), - Icon(ZetaIcons.chain_round), - Icon(ZetaIcons.contrast_round), - Icon(ZetaIcons.dark_mode_round), - Icon(ZetaIcons.devices_round), - Icon(ZetaIcons.ethernet_round), - Icon(ZetaIcons.flight_mode_round), - Icon(ZetaIcons.hdmi_round), - Icon(ZetaIcons.light_mode_round), - Icon(ZetaIcons.location_point_round), - Icon(ZetaIcons.location_round), - Icon(ZetaIcons.mobile_friendly_round), - Icon(ZetaIcons.network_signal_round), - Icon(ZetaIcons.nfc_round), - Icon(ZetaIcons.night_round), - Icon(ZetaIcons.restart_alt_round), - Icon(ZetaIcons.screen_rotation_round), - Icon(ZetaIcons.uhf_rfid_round), - Icon(ZetaIcons.usb_alt_device_round), - Icon(ZetaIcons.usb_alt_round), - Icon(ZetaIcons.usb_round), - Icon(ZetaIcons.volte_round), - Icon(ZetaIcons.appgallery_round), - Icon(ZetaIcons.application_analytics_round), - Icon(ZetaIcons.asset_tracker_lite_round), - Icon(ZetaIcons.blood_bag_plus_round), - Icon(ZetaIcons.bluetooth_management_round), - Icon(ZetaIcons.browser_print_round), - Icon(ZetaIcons.cloud_connect_round), - Icon(ZetaIcons.data_wedge_round), - Icon(ZetaIcons.design_tools_round), - Icon(ZetaIcons.device_tracker_round), - Icon(ZetaIcons.direct_connect_round), - Icon(ZetaIcons.emdk_round), - Icon(ZetaIcons.enterprise_browser_round), - Icon(ZetaIcons.enterprise_connectors_round), - Icon(ZetaIcons.enterprise_keyboard_round), - Icon(ZetaIcons.gms_restricted_mode_round), - Icon(ZetaIcons.intelligent_document_capture_round), - Icon(ZetaIcons.label_plus_round), - Icon(ZetaIcons.life_guard_round), - Icon(ZetaIcons.link_os_round), - Icon(ZetaIcons.mdm_connectors_round), - Icon(ZetaIcons.mdm_toolkit_round), - Icon(ZetaIcons.mobility_dna_round), - Icon(ZetaIcons.mobility_security_round), - Icon(ZetaIcons.multi_code_data_formatting_round), - Icon(ZetaIcons.mx_round), - Icon(ZetaIcons.ocr_round), - Icon(ZetaIcons.oem_config_round), - Icon(ZetaIcons.pairing_solutions_round), - Icon(ZetaIcons.pdf_direct_round), - Icon(ZetaIcons.power_precision_round), - Icon(ZetaIcons.preferred_symbol_round), - Icon(ZetaIcons.print_secure_round), - Icon(ZetaIcons.print_station_round), - Icon(ZetaIcons.printer_profile_manager_round), - Icon(ZetaIcons.przm_round), - Icon(ZetaIcons.remote_control_round), - Icon(ZetaIcons.remote_diagnostics_round), - Icon(ZetaIcons.remote_management_round), - Icon(ZetaIcons.rx_round), - Icon(ZetaIcons.scan_and_pair_round), - Icon(ZetaIcons.scan_speed_analytics_round), - Icon(ZetaIcons.scan_to_connect_round), - Icon(ZetaIcons.scanner_control_application_round), - Icon(ZetaIcons.setting_tool_round), - Icon(ZetaIcons.simulscan_round), - Icon(ZetaIcons.smart_te_lite_round), - Icon(ZetaIcons.smart_te_round), - Icon(ZetaIcons.smart_tek_round), - Icon(ZetaIcons.smartdex_round), - Icon(ZetaIcons.stagenow_round), - Icon(ZetaIcons.swipe_assist_round), - Icon(ZetaIcons.tekspeech_pro_round), - Icon(ZetaIcons.virtual_devices_round), - Icon(ZetaIcons.virtual_tether_round), - Icon(ZetaIcons.visibility_services_round), - Icon(ZetaIcons.voice_wedge_round), - Icon(ZetaIcons.workforce_connect_round), - Icon(ZetaIcons.workstation_connect_round), - Icon(ZetaIcons.zebra_designer_round), - Icon(ZetaIcons.zebra_onecare_round), - Icon(ZetaIcons.zebra_setup_utility_round), - Icon(ZetaIcons.zero_touch_round), - Icon(ZetaIcons.align_center_round), - Icon(ZetaIcons.align_horizontal_center_round), - Icon(ZetaIcons.align_horizontal_left_round), - Icon(ZetaIcons.align_horizontal_right_round), - Icon(ZetaIcons.align_left_round), - Icon(ZetaIcons.align_right_round), - Icon(ZetaIcons.align_vertical_bottom_round), - Icon(ZetaIcons.align_vertical_center_round), - Icon(ZetaIcons.align_vertical_top_round), - Icon(ZetaIcons.attach_round), - Icon(ZetaIcons.bold_round), - Icon(ZetaIcons.bullet_list_round), - Icon(ZetaIcons.checklist_round), - Icon(ZetaIcons.color_fill_round), - Icon(ZetaIcons.distribute_horizontal_round), - Icon(ZetaIcons.distribute_vertical_round), - Icon(ZetaIcons.edit_border_round), - Icon(ZetaIcons.edit_round), - Icon(ZetaIcons.font_size_decrease_round), - Icon(ZetaIcons.font_size_increase_round), - Icon(ZetaIcons.format_shapes_round), - Icon(ZetaIcons.indent_decrease_round), - Icon(ZetaIcons.indent_increase_round), - Icon(ZetaIcons.italic_round), - Icon(ZetaIcons.justify_round), - Icon(ZetaIcons.line_spacing_round), - Icon(ZetaIcons.link_round), - Icon(ZetaIcons.no_color_round), - Icon(ZetaIcons.numbered_list_round), - Icon(ZetaIcons.strikethrough_round), - Icon(ZetaIcons.text_color_round), - Icon(ZetaIcons.type_round), - Icon(ZetaIcons.underline_round), - Icon(ZetaIcons.barcode_bluetooth_round), - Icon(ZetaIcons.barcode_done_round), - Icon(ZetaIcons.barcode_image_scan_round), - Icon(ZetaIcons.barcode_qr_code_round), - Icon(ZetaIcons.barcode_round), - Icon(ZetaIcons.barcode_scanner_down_round), - Icon(ZetaIcons.barcode_settings_round), - Icon(ZetaIcons.calculator_round), - Icon(ZetaIcons.card_orientation_round), - Icon(ZetaIcons.card_with_chip_round), - Icon(ZetaIcons.certificate_round), - Icon(ZetaIcons.choices_round), - Icon(ZetaIcons.contactless_pay_round), - Icon(ZetaIcons.credit_card_swipe_round), - Icon(ZetaIcons.eas_round), - Icon(ZetaIcons.enterprise_diagnostics_round), - Icon(ZetaIcons.environmental_round), - Icon(ZetaIcons.factory_round), - Icon(ZetaIcons.freezer_round), - Icon(ZetaIcons.issue_audit_round), - Icon(ZetaIcons.performance_round), - Icon(ZetaIcons.planogram_round), - Icon(ZetaIcons.productivity_apps_round), - Icon(ZetaIcons.receipt_round), - Icon(ZetaIcons.retail_round), - Icon(ZetaIcons.road_map_round), - Icon(ZetaIcons.rules_round), - Icon(ZetaIcons.scan_rate_round), - Icon(ZetaIcons.shape_recognition_round), - Icon(ZetaIcons.solutions_round), - Icon(ZetaIcons.steps_round), - Icon(ZetaIcons.strategy_round), - Icon(ZetaIcons.tap_to_pay_round), - Icon(ZetaIcons.zero_scale_round), - Icon(ZetaIcons.attachment_round), - Icon(ZetaIcons.cloud_done_round), - Icon(ZetaIcons.cloud_download_round), - Icon(ZetaIcons.cloud_off_round), - Icon(ZetaIcons.cloud_outline_round), - Icon(ZetaIcons.cloud_round), - Icon(ZetaIcons.cloud_upload_round), - Icon(ZetaIcons.create_new_folder_round), - Icon(ZetaIcons.doc_attach_round), - Icon(ZetaIcons.downloading_round), - Icon(ZetaIcons.file_download_round), - Icon(ZetaIcons.file_upload_round), - Icon(ZetaIcons.finished_download_round), - Icon(ZetaIcons.folder_outline_round), - Icon(ZetaIcons.folder_round), - Icon(ZetaIcons.grid_view_round), - Icon(ZetaIcons.jpg_attach_round), - Icon(ZetaIcons.pdf_attach_round), - Icon(ZetaIcons.png_attach_round), - Icon(ZetaIcons.ppt_attach_round), - Icon(ZetaIcons.shared_folder_round), - Icon(ZetaIcons.upload_file_round), - Icon(ZetaIcons.cast_connected_round), - Icon(ZetaIcons.cast_round), - Icon(ZetaIcons.desktop_round), - Icon(ZetaIcons.device_settings_round), - Icon(ZetaIcons.devices_ecosystem_round), - Icon(ZetaIcons.headphones_round), - Icon(ZetaIcons.keyboard_round), - Icon(ZetaIcons.laptop_round), - Icon(ZetaIcons.memory_round), - Icon(ZetaIcons.monitor_round), - Icon(ZetaIcons.phone_android_round), - Icon(ZetaIcons.phone_iphone_round), - Icon(ZetaIcons.phonelink_round), - Icon(ZetaIcons.printer_round), - Icon(ZetaIcons.scanner_round), - Icon(ZetaIcons.security_round), - Icon(ZetaIcons.smart_phone_round), - Icon(ZetaIcons.speaker_round), - Icon(ZetaIcons.tablet_mac_round), - Icon(ZetaIcons.tablet_round), - Icon(ZetaIcons.tv_round), - Icon(ZetaIcons.video_play_round), - Icon(ZetaIcons.watch_round), - Icon(ZetaIcons.adjustments_round), - Icon(ZetaIcons.auto_round), - Icon(ZetaIcons.awb_round), - Icon(ZetaIcons.camera_round), - Icon(ZetaIcons.camera_shutter_round), - Icon(ZetaIcons.contrast_image_round), - Icon(ZetaIcons.crop_round), - Icon(ZetaIcons.eye_dropper_round), - Icon(ZetaIcons.flip_camera_round), - Icon(ZetaIcons.grid_off_round), - Icon(ZetaIcons.grid_on_round), - Icon(ZetaIcons.hdr_round), - Icon(ZetaIcons.image_library_round), - Icon(ZetaIcons.image_round), - Icon(ZetaIcons.iso_round), - Icon(ZetaIcons.portrait_round), - Icon(ZetaIcons.pro_round), - Icon(ZetaIcons.rotate_left_round), - Icon(ZetaIcons.rotate_right_round), - Icon(ZetaIcons.slide_show_round), - Icon(ZetaIcons.straighten_round), - Icon(ZetaIcons.timer_round), - Icon(ZetaIcons.visibility_image_round), - Icon(ZetaIcons.visibility_off_image_round), - Icon(ZetaIcons.wb_image_round), - Icon(ZetaIcons.wb_round), - Icon(ZetaIcons.bus_round), - Icon(ZetaIcons.cafe_round), - Icon(ZetaIcons.car_round), - Icon(ZetaIcons.flight_round), - Icon(ZetaIcons.layers_round), - Icon(ZetaIcons.light_rail_train_round), - Icon(ZetaIcons.local_shipping_round), - Icon(ZetaIcons.map_round), - Icon(ZetaIcons.my_location_round), - Icon(ZetaIcons.navigation_round), - Icon(ZetaIcons.near_me_round), - Icon(ZetaIcons.offer_round), - Icon(ZetaIcons.place_round), - Icon(ZetaIcons.ship_round), - Icon(ZetaIcons.taxi_round), - Icon(ZetaIcons.train_round), - Icon(ZetaIcons.world_round), - Icon(ZetaIcons.zoom_in_map_round), - Icon(ZetaIcons.zoom_out_map_round), - Icon(ZetaIcons.apps_round), - Icon(ZetaIcons.arrow_back_round), - Icon(ZetaIcons.arrow_down_round), - Icon(ZetaIcons.arrow_forward_round), - Icon(ZetaIcons.arrow_up_round), - Icon(ZetaIcons.cancel_outline_round), - Icon(ZetaIcons.cancel_round), - Icon(ZetaIcons.caret_down_round), - Icon(ZetaIcons.caret_left_round), - Icon(ZetaIcons.caret_right_round), - Icon(ZetaIcons.caret_sort_round), - Icon(ZetaIcons.caret_up_round), - Icon(ZetaIcons.check_round), - Icon(ZetaIcons.chevron_left_round), - Icon(ZetaIcons.chevron_right_round), - Icon(ZetaIcons.close_round), - Icon(ZetaIcons.columns_round), - Icon(ZetaIcons.dashboard_round), - Icon(ZetaIcons.drop_down_circle_round), - Icon(ZetaIcons.expand_less_round), - Icon(ZetaIcons.expand_more_round), - Icon(ZetaIcons.first_page_round), - Icon(ZetaIcons.full_screen_exit_round), - Icon(ZetaIcons.full_screen_round), - Icon(ZetaIcons.hamburger_menu_navigation_rail_round), - Icon(ZetaIcons.hamburger_menu_round), - Icon(ZetaIcons.hamburger_menu_thick_round), - Icon(ZetaIcons.help_outline_round), - Icon(ZetaIcons.help_round), - Icon(ZetaIcons.last_page_round), - Icon(ZetaIcons.list_alt_round), - Icon(ZetaIcons.list_round), - Icon(ZetaIcons.more_horizontal_round), - Icon(ZetaIcons.more_vertical_round), - Icon(ZetaIcons.refresh_round), - Icon(ZetaIcons.unfold_less_round), - Icon(ZetaIcons.unfold_more_round), - Icon(ZetaIcons.add_group_round), - Icon(ZetaIcons.add_person_round), - Icon(ZetaIcons.bad_mood_round), - Icon(ZetaIcons.blog_round), - Icon(ZetaIcons.dislike_round), - Icon(ZetaIcons.facebook_round), - Icon(ZetaIcons.group_round), - Icon(ZetaIcons.groups_round), - Icon(ZetaIcons.happy_round), - Icon(ZetaIcons.instagram_round), - Icon(ZetaIcons.ios_share_round), - Icon(ZetaIcons.like_round), - Icon(ZetaIcons.linkedin_round), - Icon(ZetaIcons.medium_round), - Icon(ZetaIcons.notifications_active_round), - Icon(ZetaIcons.notifications_outline_round), - Icon(ZetaIcons.notifications_round), - Icon(ZetaIcons.person_outline_round), - Icon(ZetaIcons.person_round), - Icon(ZetaIcons.remove_group_round), - Icon(ZetaIcons.remove_person_round), - Icon(ZetaIcons.sad_round), - Icon(ZetaIcons.satisfied_round), - Icon(ZetaIcons.share_round), - Icon(ZetaIcons.switch_user_round), - Icon(ZetaIcons.twitter_round), - Icon(ZetaIcons.very_satisfied_round), - Icon(ZetaIcons.world_map_round), - Icon(ZetaIcons.youtube_round), - Icon(ZetaIcons.check_box_empty_round), - Icon(ZetaIcons.check_box_round), - Icon(ZetaIcons.indeterminate_check_box_round), - Icon(ZetaIcons.radio_button_checked_round), - Icon(ZetaIcons.radio_button_unchecked_round), - Icon(ZetaIcons.star_half_round), - Icon(ZetaIcons.star_outline_round), - Icon(ZetaIcons.star_round), - Icon(ZetaIcons.toggle_off_round), - Icon(ZetaIcons.toggle_on_round), - ], - ), - const SizedBox(height: 20), - Text('Sharp', style: ZetaTextStyles.bodyLarge), - Wrap( - spacing: 8, - runSpacing: 8, - children: [ - Icon(ZetaIcons.alarm_sharp), - Icon(ZetaIcons.ar_sharp), - Icon(ZetaIcons.bookmark_outline_sharp), - Icon(ZetaIcons.bookmark_sharp), - Icon(ZetaIcons.build_sharp), - Icon(ZetaIcons.cached_sharp), - Icon(ZetaIcons.calendar_3_day_sharp), - Icon(ZetaIcons.calendar_alt_1_sharp), - Icon(ZetaIcons.calendar_alt_2_sharp), - Icon(ZetaIcons.calendar_available_sharp), - Icon(ZetaIcons.calendar_cancel_sharp), - Icon(ZetaIcons.calendar_day_sharp), - Icon(ZetaIcons.calendar_edit_sharp), - Icon(ZetaIcons.calendar_monthly_alt_sharp), - Icon(ZetaIcons.calendar_monthly_sharp), - Icon(ZetaIcons.calendar_range_sharp), - Icon(ZetaIcons.calendar_sharp), - Icon(ZetaIcons.calendar_weekly_alt_sharp), - Icon(ZetaIcons.calendar_weekly_sharp), - Icon(ZetaIcons.calendar_yearly_sharp), - Icon(ZetaIcons.check_circle_outline_alt_sharp), - Icon(ZetaIcons.check_circle_outline_sharp), - Icon(ZetaIcons.check_circle_sharp), - Icon(ZetaIcons.check_mark_sharp), - Icon(ZetaIcons.clipboard_sharp), - Icon(ZetaIcons.clock_outline_sharp), - Icon(ZetaIcons.clock_sharp), - Icon(ZetaIcons.credit_card_sharp), - Icon(ZetaIcons.delete_forever_sharp), - Icon(ZetaIcons.delete_outline_sharp), - Icon(ZetaIcons.delete_sharp), - Icon(ZetaIcons.dislike_action_sharp), - Icon(ZetaIcons.document_sharp), - Icon(ZetaIcons.download_sharp), - Icon(ZetaIcons.filter_alt_sharp), - Icon(ZetaIcons.filter_sharp), - Icon(ZetaIcons.hand_sharp), - Icon(ZetaIcons.history_sharp), - Icon(ZetaIcons.home_sharp), - Icon(ZetaIcons.info_sharp), - Icon(ZetaIcons.label_sharp), - Icon(ZetaIcons.like_action_sharp), - Icon(ZetaIcons.lock_alt_sharp), - Icon(ZetaIcons.lock_sharp), - Icon(ZetaIcons.log_in_sharp), - Icon(ZetaIcons.log_out_sharp), - Icon(ZetaIcons.love_outline_sharp), - Icon(ZetaIcons.love_sharp), - Icon(ZetaIcons.open_in_full_sharp), - Icon(ZetaIcons.open_in_new_window_sharp), - Icon(ZetaIcons.pending_sharp), - Icon(ZetaIcons.pin_sharp), - Icon(ZetaIcons.price_sharp), - Icon(ZetaIcons.renew_sharp), - Icon(ZetaIcons.search_sharp), - Icon(ZetaIcons.security_check_sharp), - Icon(ZetaIcons.settings_sharp), - Icon(ZetaIcons.sync_action_sharp), - Icon(ZetaIcons.touch_sharp), - Icon(ZetaIcons.trending_down_sharp), - Icon(ZetaIcons.trending_up_sharp), - Icon(ZetaIcons.unlock_alt_sharp), - Icon(ZetaIcons.unlock_sharp), - Icon(ZetaIcons.update_sharp), - Icon(ZetaIcons.upload_sharp), - Icon(ZetaIcons.user_circle_sharp), - Icon(ZetaIcons.user_sharp), - Icon(ZetaIcons.user_settings_sharp), - Icon(ZetaIcons.verified_sharp), - Icon(ZetaIcons.visibility_off_sharp), - Icon(ZetaIcons.visibility_sharp), - Icon(ZetaIcons.world_action_sharp), - Icon(ZetaIcons.zoom_in_sharp), - Icon(ZetaIcons.zoom_out_sharp), - Icon(ZetaIcons.add_alert_sharp), - Icon(ZetaIcons.alert_sharp), - Icon(ZetaIcons.auto_delete_sharp), - Icon(ZetaIcons.error_outline_sharp), - Icon(ZetaIcons.error_sharp), - Icon(ZetaIcons.important_notification_sharp), - Icon(ZetaIcons.warning_outline_sharp), - Icon(ZetaIcons.warning_sharp), - Icon(ZetaIcons.block_sharp), - Icon(ZetaIcons.closed_caption_sharp), - Icon(ZetaIcons.fast_forward_sharp), - Icon(ZetaIcons.fast_rewind_sharp), - Icon(ZetaIcons.loop_sharp), - Icon(ZetaIcons.microphone_off_sharp), - Icon(ZetaIcons.microphone_outline_sharp), - Icon(ZetaIcons.microphone_sharp), - Icon(ZetaIcons.pause_circle_sharp), - Icon(ZetaIcons.pause_sharp), - Icon(ZetaIcons.play_circle_sharp), - Icon(ZetaIcons.play_outline_sharp), - Icon(ZetaIcons.play_sharp), - Icon(ZetaIcons.replay_sharp), - Icon(ZetaIcons.skip_next_sharp), - Icon(ZetaIcons.skip_previous_sharp), - Icon(ZetaIcons.stop_circle_sharp), - Icon(ZetaIcons.stop_sharp), - Icon(ZetaIcons.video_camera_sharp), - Icon(ZetaIcons.volume_down_sharp), - Icon(ZetaIcons.volume_mute_sharp), - Icon(ZetaIcons.volume_off_sharp), - Icon(ZetaIcons.volume_up_sharp), - Icon(ZetaIcons.add_call_sharp), - Icon(ZetaIcons.chat_bubble_outline_sharp), - Icon(ZetaIcons.chat_bubble_sharp), - Icon(ZetaIcons.conversation_sharp), - Icon(ZetaIcons.dialpad_sharp), - Icon(ZetaIcons.do_not_disturb_sharp), - Icon(ZetaIcons.dollar_sharp), - Icon(ZetaIcons.email_alt_sharp), - Icon(ZetaIcons.email_outline_sharp), - Icon(ZetaIcons.email_sharp), - Icon(ZetaIcons.end_call_sharp), - Icon(ZetaIcons.message_sharp), - Icon(ZetaIcons.person_search_sharp), - Icon(ZetaIcons.phone_bluetooth_speaker_sharp), - Icon(ZetaIcons.phone_in_talk_sharp), - Icon(ZetaIcons.phone_sharp), - Icon(ZetaIcons.priority_sharp), - Icon(ZetaIcons.qr_code_sharp), - Icon(ZetaIcons.qr_code_scan_sharp), - Icon(ZetaIcons.rss_feed_sharp), - Icon(ZetaIcons.sd_card_sharp), - Icon(ZetaIcons.sim_card_sharp), - Icon(ZetaIcons.sms_sharp), - Icon(ZetaIcons.sync_disabled_sharp), - Icon(ZetaIcons.sync_sharp), - Icon(ZetaIcons.add_box_sharp), - Icon(ZetaIcons.add_circle_outline_sharp), - Icon(ZetaIcons.add_circle_sharp), - Icon(ZetaIcons.add_sharp), - Icon(ZetaIcons.analysis_sharp), - Icon(ZetaIcons.android_sharp), - Icon(ZetaIcons.backspace_sharp), - Icon(ZetaIcons.block_content_sharp), - Icon(ZetaIcons.clear_sharp), - Icon(ZetaIcons.content_sharp), - Icon(ZetaIcons.copy_file_sharp), - Icon(ZetaIcons.create_sharp), - Icon(ZetaIcons.filter_list_sharp), - Icon(ZetaIcons.flag_sharp), - Icon(ZetaIcons.link_content_sharp), - Icon(ZetaIcons.mail_sharp), - Icon(ZetaIcons.push_pin_sharp), - Icon(ZetaIcons.redo_sharp), - Icon(ZetaIcons.remove_box_sharp), - Icon(ZetaIcons.remove_circle_outline_sharp), - Icon(ZetaIcons.remove_circle_sharp), - Icon(ZetaIcons.remove_sharp), - Icon(ZetaIcons.reply_sharp), - Icon(ZetaIcons.save_alt_sharp), - Icon(ZetaIcons.save_sharp), - Icon(ZetaIcons.send_sharp), - Icon(ZetaIcons.sort_sharp), - Icon(ZetaIcons.undo_sharp), - Icon(ZetaIcons.antenna_sharp), - Icon(ZetaIcons.battery_alert_sharp), - Icon(ZetaIcons.battery_charging_sharp), - Icon(ZetaIcons.battery_sharp), - Icon(ZetaIcons.bluetooth_disabled_sharp), - Icon(ZetaIcons.bluetooth_sharp), - Icon(ZetaIcons.bluetooth_searching_sharp), - Icon(ZetaIcons.brightness_sharp), - Icon(ZetaIcons.cellular_signal_sharp), - Icon(ZetaIcons.chain_sharp), - Icon(ZetaIcons.contrast_sharp), - Icon(ZetaIcons.dark_mode_sharp), - Icon(ZetaIcons.devices_sharp), - Icon(ZetaIcons.ethernet_sharp), - Icon(ZetaIcons.flight_mode_sharp), - Icon(ZetaIcons.hdmi_sharp), - Icon(ZetaIcons.light_mode_sharp), - Icon(ZetaIcons.location_point_sharp), - Icon(ZetaIcons.location_sharp), - Icon(ZetaIcons.mobile_friendly_sharp), - Icon(ZetaIcons.network_signal_sharp), - Icon(ZetaIcons.nfc_sharp), - Icon(ZetaIcons.night_sharp), - Icon(ZetaIcons.restart_alt_sharp), - Icon(ZetaIcons.screen_rotation_sharp), - Icon(ZetaIcons.uhf_rfid_sharp), - Icon(ZetaIcons.usb_alt_device_sharp), - Icon(ZetaIcons.usb_alt_sharp), - Icon(ZetaIcons.usb_sharp), - Icon(ZetaIcons.volte_sharp), - Icon(ZetaIcons.appgallery_sharp), - Icon(ZetaIcons.application_analytics_sharp), - Icon(ZetaIcons.asset_tracker_lite_sharp), - Icon(ZetaIcons.blood_bag_plus_sharp), - Icon(ZetaIcons.bluetooth_management_sharp), - Icon(ZetaIcons.browser_print_sharp), - Icon(ZetaIcons.cloud_connect_sharp), - Icon(ZetaIcons.data_wedge_sharp), - Icon(ZetaIcons.design_tools_sharp), - Icon(ZetaIcons.device_tracker_sharp), - Icon(ZetaIcons.direct_connect_sharp), - Icon(ZetaIcons.emdk_sharp), - Icon(ZetaIcons.enterprise_browser_sharp), - Icon(ZetaIcons.enterprise_connectors_sharp), - Icon(ZetaIcons.enterprise_keyboard_sharp), - Icon(ZetaIcons.gms_restricted_mode_sharp), - Icon(ZetaIcons.intelligent_document_capture_sharp), - Icon(ZetaIcons.label_plus_sharp), - Icon(ZetaIcons.life_guard_sharp), - Icon(ZetaIcons.link_os_sharp), - Icon(ZetaIcons.mdm_connectors_sharp), - Icon(ZetaIcons.mdm_toolkit_sharp), - Icon(ZetaIcons.mobility_dna_sharp), - Icon(ZetaIcons.mobility_security_sharp), - Icon(ZetaIcons.multi_code_data_formatting_sharp), - Icon(ZetaIcons.mx_sharp), - Icon(ZetaIcons.ocr_sharp), - Icon(ZetaIcons.oem_config_sharp), - Icon(ZetaIcons.pairing_solutions_sharp), - Icon(ZetaIcons.pdf_direct_sharp), - Icon(ZetaIcons.power_precision_sharp), - Icon(ZetaIcons.preferred_symbol_sharp), - Icon(ZetaIcons.print_secure_sharp), - Icon(ZetaIcons.print_station_sharp), - Icon(ZetaIcons.printer_profile_manager_sharp), - Icon(ZetaIcons.przm_sharp), - Icon(ZetaIcons.remote_control_sharp), - Icon(ZetaIcons.remote_diagnostics_sharp), - Icon(ZetaIcons.remote_management_sharp), - Icon(ZetaIcons.rx_sharp), - Icon(ZetaIcons.scan_and_pair_sharp), - Icon(ZetaIcons.scan_speed_analytics_sharp), - Icon(ZetaIcons.scan_to_connect_sharp), - Icon(ZetaIcons.scanner_control_application_sharp), - Icon(ZetaIcons.setting_tool_sharp), - Icon(ZetaIcons.simulscan_sharp), - Icon(ZetaIcons.smart_te_lite_sharp), - Icon(ZetaIcons.smart_te_sharp), - Icon(ZetaIcons.smart_tek_sharp), - Icon(ZetaIcons.smartdex_sharp), - Icon(ZetaIcons.stagenow_sharp), - Icon(ZetaIcons.swipe_assist_sharp), - Icon(ZetaIcons.tekspeech_pro_sharp), - Icon(ZetaIcons.virtual_devices_sharp), - Icon(ZetaIcons.virtual_tether_sharp), - Icon(ZetaIcons.visibility_services_sharp), - Icon(ZetaIcons.voice_wedge_sharp), - Icon(ZetaIcons.workforce_connect_sharp), - Icon(ZetaIcons.workstation_connect_sharp), - Icon(ZetaIcons.zebra_designer_sharp), - Icon(ZetaIcons.zebra_onecare_sharp), - Icon(ZetaIcons.zebra_setup_utility_sharp), - Icon(ZetaIcons.zero_touch_sharp), - Icon(ZetaIcons.align_center_sharp), - Icon(ZetaIcons.align_horizontal_center_sharp), - Icon(ZetaIcons.align_horizontal_left_sharp), - Icon(ZetaIcons.align_horizontal_right_sharp), - Icon(ZetaIcons.align_left_sharp), - Icon(ZetaIcons.align_right_sharp), - Icon(ZetaIcons.align_vertical_bottom_sharp), - Icon(ZetaIcons.align_vertical_center_sharp), - Icon(ZetaIcons.align_vertical_top_sharp), - Icon(ZetaIcons.attach_sharp), - Icon(ZetaIcons.bold_sharp), - Icon(ZetaIcons.bullet_list_sharp), - Icon(ZetaIcons.checklist_sharp), - Icon(ZetaIcons.color_fill_sharp), - Icon(ZetaIcons.distribute_horizontal_sharp), - Icon(ZetaIcons.distribute_vertical_sharp), - Icon(ZetaIcons.edit_border_sharp), - Icon(ZetaIcons.edit_sharp), - Icon(ZetaIcons.font_size_decrease_sharp), - Icon(ZetaIcons.font_size_increase_sharp), - Icon(ZetaIcons.format_shapes_sharp), - Icon(ZetaIcons.indent_decrease_sharp), - Icon(ZetaIcons.indent_increase_sharp), - Icon(ZetaIcons.italic_sharp), - Icon(ZetaIcons.justify_sharp), - Icon(ZetaIcons.line_spacing_sharp), - Icon(ZetaIcons.link_sharp), - Icon(ZetaIcons.no_color_sharp), - Icon(ZetaIcons.numbered_list_sharp), - Icon(ZetaIcons.strikethrough_sharp), - Icon(ZetaIcons.text_color_sharp), - Icon(ZetaIcons.type_sharp), - Icon(ZetaIcons.underline_sharp), - Icon(ZetaIcons.barcode_bluetooth_sharp), - Icon(ZetaIcons.barcode_done_sharp), - Icon(ZetaIcons.barcode_image_scan_sharp), - Icon(ZetaIcons.barcode_qr_code_sharp), - Icon(ZetaIcons.barcode_sharp), - Icon(ZetaIcons.barcode_scanner_down_sharp), - Icon(ZetaIcons.barcode_settings_sharp), - Icon(ZetaIcons.calculator_sharp), - Icon(ZetaIcons.card_orientation_sharp), - Icon(ZetaIcons.card_with_chip_sharp), - Icon(ZetaIcons.certificate_sharp), - Icon(ZetaIcons.choices_sharp), - Icon(ZetaIcons.contactless_pay_sharp), - Icon(ZetaIcons.credit_card_swipe_sharp), - Icon(ZetaIcons.eas_sharp), - Icon(ZetaIcons.enterprise_diagnostics_sharp), - Icon(ZetaIcons.environmental_sharp), - Icon(ZetaIcons.factory_sharp), - Icon(ZetaIcons.freezer_sharp), - Icon(ZetaIcons.issue_audit_sharp), - Icon(ZetaIcons.performance_sharp), - Icon(ZetaIcons.planogram_sharp), - Icon(ZetaIcons.productivity_apps_sharp), - Icon(ZetaIcons.receipt_sharp), - Icon(ZetaIcons.retail_sharp), - Icon(ZetaIcons.road_map_sharp), - Icon(ZetaIcons.rules_sharp), - Icon(ZetaIcons.scan_rate_sharp), - Icon(ZetaIcons.shape_recognition_sharp), - Icon(ZetaIcons.solutions_sharp), - Icon(ZetaIcons.steps_sharp), - Icon(ZetaIcons.strategy_sharp), - Icon(ZetaIcons.tap_to_pay_sharp), - Icon(ZetaIcons.zero_scale_sharp), - Icon(ZetaIcons.attachment_sharp), - Icon(ZetaIcons.cloud_done_sharp), - Icon(ZetaIcons.cloud_download_sharp), - Icon(ZetaIcons.cloud_off_sharp), - Icon(ZetaIcons.cloud_outline_sharp), - Icon(ZetaIcons.cloud_sharp), - Icon(ZetaIcons.cloud_upload_sharp), - Icon(ZetaIcons.create_new_folder_sharp), - Icon(ZetaIcons.doc_attach_sharp), - Icon(ZetaIcons.downloading_sharp), - Icon(ZetaIcons.file_download_sharp), - Icon(ZetaIcons.file_upload_sharp), - Icon(ZetaIcons.finished_download_sharp), - Icon(ZetaIcons.folder_outline_sharp), - Icon(ZetaIcons.folder_sharp), - Icon(ZetaIcons.grid_view_sharp), - Icon(ZetaIcons.jpg_attach_sharp), - Icon(ZetaIcons.pdf_attach_sharp), - Icon(ZetaIcons.png_attach_sharp), - Icon(ZetaIcons.ppt_attach_sharp), - Icon(ZetaIcons.shared_folder_sharp), - Icon(ZetaIcons.upload_file_sharp), - Icon(ZetaIcons.cast_connected_sharp), - Icon(ZetaIcons.cast_sharp), - Icon(ZetaIcons.desktop_sharp), - Icon(ZetaIcons.device_settings_sharp), - Icon(ZetaIcons.devices_ecosystem_sharp), - Icon(ZetaIcons.headphones_sharp), - Icon(ZetaIcons.keyboard_sharp), - Icon(ZetaIcons.laptop_sharp), - Icon(ZetaIcons.memory_sharp), - Icon(ZetaIcons.monitor_sharp), - Icon(ZetaIcons.phone_android_sharp), - Icon(ZetaIcons.phone_iphone_sharp), - Icon(ZetaIcons.phonelink_sharp), - Icon(ZetaIcons.printer_sharp), - Icon(ZetaIcons.scanner_sharp), - Icon(ZetaIcons.security_sharp), - Icon(ZetaIcons.smart_phone_sharp), - Icon(ZetaIcons.speaker_sharp), - Icon(ZetaIcons.tablet_mac_sharp), - Icon(ZetaIcons.tablet_sharp), - Icon(ZetaIcons.tv_sharp), - Icon(ZetaIcons.video_play_sharp), - Icon(ZetaIcons.watch_sharp), - Icon(ZetaIcons.adjustments_sharp), - Icon(ZetaIcons.auto_sharp), - Icon(ZetaIcons.awb_sharp), - Icon(ZetaIcons.camera_sharp), - Icon(ZetaIcons.camera_shutter_sharp), - Icon(ZetaIcons.contrast_image_sharp), - Icon(ZetaIcons.crop_sharp), - Icon(ZetaIcons.eye_dropper_sharp), - Icon(ZetaIcons.flip_camera_sharp), - Icon(ZetaIcons.grid_off_sharp), - Icon(ZetaIcons.grid_on_sharp), - Icon(ZetaIcons.hdr_sharp), - Icon(ZetaIcons.image_library_sharp), - Icon(ZetaIcons.image_sharp), - Icon(ZetaIcons.iso_sharp), - Icon(ZetaIcons.portrait_sharp), - Icon(ZetaIcons.pro_sharp), - Icon(ZetaIcons.rotate_left_sharp), - Icon(ZetaIcons.rotate_right_sharp), - Icon(ZetaIcons.slide_show_sharp), - Icon(ZetaIcons.straighten_sharp), - Icon(ZetaIcons.timer_sharp), - Icon(ZetaIcons.visibility_image_sharp), - Icon(ZetaIcons.visibility_off_image_sharp), - Icon(ZetaIcons.wb_image_sharp), - Icon(ZetaIcons.wb_sharp), - Icon(ZetaIcons.bus_sharp), - Icon(ZetaIcons.cafe_sharp), - Icon(ZetaIcons.car_sharp), - Icon(ZetaIcons.flight_sharp), - Icon(ZetaIcons.layers_sharp), - Icon(ZetaIcons.light_rail_train_sharp), - Icon(ZetaIcons.local_shipping_sharp), - Icon(ZetaIcons.map_sharp), - Icon(ZetaIcons.my_location_sharp), - Icon(ZetaIcons.navigation_sharp), - Icon(ZetaIcons.near_me_sharp), - Icon(ZetaIcons.offer_sharp), - Icon(ZetaIcons.place_sharp), - Icon(ZetaIcons.ship_sharp), - Icon(ZetaIcons.taxi_sharp), - Icon(ZetaIcons.train_sharp), - Icon(ZetaIcons.world_sharp), - Icon(ZetaIcons.zoom_in_map_sharp), - Icon(ZetaIcons.zoom_out_map_sharp), - Icon(ZetaIcons.apps_sharp), - Icon(ZetaIcons.arrow_back_sharp), - Icon(ZetaIcons.arrow_down_sharp), - Icon(ZetaIcons.arrow_forward_sharp), - Icon(ZetaIcons.arrow_up_sharp), - Icon(ZetaIcons.cancel_outline_sharp), - Icon(ZetaIcons.cancel_sharp), - Icon(ZetaIcons.caret_down_sharp), - Icon(ZetaIcons.caret_left_sharp), - Icon(ZetaIcons.caret_right_sharp), - Icon(ZetaIcons.caret_sort_sharp), - Icon(ZetaIcons.caret_up_sharp), - Icon(ZetaIcons.check_sharp), - Icon(ZetaIcons.chevron_left_sharp), - Icon(ZetaIcons.chevron_right_sharp), - Icon(ZetaIcons.close_sharp), - Icon(ZetaIcons.columns_sharp), - Icon(ZetaIcons.dashboard_sharp), - Icon(ZetaIcons.drop_down_circle_sharp), - Icon(ZetaIcons.expand_less_sharp), - Icon(ZetaIcons.expand_more_sharp), - Icon(ZetaIcons.first_page_sharp), - Icon(ZetaIcons.full_screen_exit_sharp), - Icon(ZetaIcons.full_screen_sharp), - Icon(ZetaIcons.hamburger_menu_navigation_rail_sharp), - Icon(ZetaIcons.hamburger_menu_sharp), - Icon(ZetaIcons.hamburger_menu_thick_sharp), - Icon(ZetaIcons.help_outline_sharp), - Icon(ZetaIcons.help_sharp), - Icon(ZetaIcons.last_page_sharp), - Icon(ZetaIcons.list_alt_sharp), - Icon(ZetaIcons.list_sharp), - Icon(ZetaIcons.more_horizontal_sharp), - Icon(ZetaIcons.more_vertical_sharp), - Icon(ZetaIcons.refresh_sharp), - Icon(ZetaIcons.unfold_less_sharp), - Icon(ZetaIcons.unfold_more_sharp), - Icon(ZetaIcons.add_group_sharp), - Icon(ZetaIcons.add_person_sharp), - Icon(ZetaIcons.bad_mood_sharp), - Icon(ZetaIcons.blog_sharp), - Icon(ZetaIcons.dislike_sharp), - Icon(ZetaIcons.facebook_sharp), - Icon(ZetaIcons.group_sharp), - Icon(ZetaIcons.groups_sharp), - Icon(ZetaIcons.happy_sharp), - Icon(ZetaIcons.instagram_sharp), - Icon(ZetaIcons.ios_share_sharp), - Icon(ZetaIcons.like_sharp), - Icon(ZetaIcons.linkedin_sharp), - Icon(ZetaIcons.medium_sharp), - Icon(ZetaIcons.notifications_active_sharp), - Icon(ZetaIcons.notifications_outline_sharp), - Icon(ZetaIcons.notifications_sharp), - Icon(ZetaIcons.person_outline_sharp), - Icon(ZetaIcons.person_sharp), - Icon(ZetaIcons.remove_group_sharp), - Icon(ZetaIcons.remove_person_sharp), - Icon(ZetaIcons.sad_sharp), - Icon(ZetaIcons.satisfied_sharp), - Icon(ZetaIcons.share_sharp), - Icon(ZetaIcons.switch_user_sharp), - Icon(ZetaIcons.twitter_sharp), - Icon(ZetaIcons.very_satisfied_sharp), - Icon(ZetaIcons.world_map_sharp), - Icon(ZetaIcons.youtube_sharp), - Icon(ZetaIcons.check_box_empty_sharp), - Icon(ZetaIcons.check_box_sharp), - Icon(ZetaIcons.indeterminate_check_box_sharp), - Icon(ZetaIcons.radio_button_checked_sharp), - Icon(ZetaIcons.radio_button_unchecked_sharp), - Icon(ZetaIcons.star_half_sharp), - Icon(ZetaIcons.star_outline_sharp), - Icon(ZetaIcons.star_sharp), - Icon(ZetaIcons.toggle_off_sharp), - Icon(ZetaIcons.toggle_on_sharp), - ], - ), + // round + Icon(ZetaIcons.alarm_round), + Icon(ZetaIcons.ar_round), + Icon(ZetaIcons.bookmark_outline_round), + Icon(ZetaIcons.bookmark_round), + Icon(ZetaIcons.build_round), + Icon(ZetaIcons.cached_round), + Icon(ZetaIcons.calendar_3_day_round), + Icon(ZetaIcons.calendar_alt_1_round), + Icon(ZetaIcons.calendar_alt_2_round), + Icon(ZetaIcons.calendar_available_round), + Icon(ZetaIcons.calendar_cancel_round), + Icon(ZetaIcons.calendar_day_round), + Icon(ZetaIcons.calendar_edit_round), + Icon(ZetaIcons.calendar_monthly_alt_round), + Icon(ZetaIcons.calendar_monthly_round), + Icon(ZetaIcons.calendar_range_round), + Icon(ZetaIcons.calendar_round), + Icon(ZetaIcons.calendar_weekly_alt_round), + Icon(ZetaIcons.calendar_weekly_round), + Icon(ZetaIcons.calendar_yearly_round), + Icon(ZetaIcons.check_circle_outline_alt_round), + Icon(ZetaIcons.check_circle_outline_round), + Icon(ZetaIcons.check_circle_round), + Icon(ZetaIcons.check_mark_round), + Icon(ZetaIcons.clipboard_round), + Icon(ZetaIcons.clock_outline_round), + Icon(ZetaIcons.clock_round), + Icon(ZetaIcons.credit_card_round), + Icon(ZetaIcons.delete_forever_round), + Icon(ZetaIcons.delete_outline_round), + Icon(ZetaIcons.delete_round), + Icon(ZetaIcons.dislike_action_round), + Icon(ZetaIcons.document_round), + Icon(ZetaIcons.download_round), + Icon(ZetaIcons.filter_alt_round), + Icon(ZetaIcons.filter_round), + Icon(ZetaIcons.hand_round), + Icon(ZetaIcons.history_round), + Icon(ZetaIcons.home_round), + Icon(ZetaIcons.info_round), + Icon(ZetaIcons.label_round), + Icon(ZetaIcons.like_action_round), + Icon(ZetaIcons.lock_alt_round), + Icon(ZetaIcons.lock_round), + Icon(ZetaIcons.log_in_round), + Icon(ZetaIcons.log_out_round), + Icon(ZetaIcons.love_outline_round), + Icon(ZetaIcons.love_round), + Icon(ZetaIcons.open_in_full_round), + Icon(ZetaIcons.open_in_new_window_round), + Icon(ZetaIcons.pending_round), + Icon(ZetaIcons.pin_round), + Icon(ZetaIcons.price_round), + Icon(ZetaIcons.renew_round), + Icon(ZetaIcons.search_round), + Icon(ZetaIcons.security_check_round), + Icon(ZetaIcons.settings_round), + Icon(ZetaIcons.sync_action_round), + Icon(ZetaIcons.touch_round), + Icon(ZetaIcons.trending_down_round), + Icon(ZetaIcons.trending_up_round), + Icon(ZetaIcons.unlock_alt_round), + Icon(ZetaIcons.unlock_round), + Icon(ZetaIcons.update_round), + Icon(ZetaIcons.upload_round), + Icon(ZetaIcons.user_circle_round), + Icon(ZetaIcons.user_round), + Icon(ZetaIcons.user_settings_round), + Icon(ZetaIcons.verified_round), + Icon(ZetaIcons.visibility_off_round), + Icon(ZetaIcons.visibility_round), + Icon(ZetaIcons.world_action_round), + Icon(ZetaIcons.zoom_in_round), + Icon(ZetaIcons.zoom_out_round), + Icon(ZetaIcons.add_alert_round), + Icon(ZetaIcons.alert_round), + Icon(ZetaIcons.auto_delete_round), + Icon(ZetaIcons.error_outline_round), + Icon(ZetaIcons.error_round), + Icon(ZetaIcons.important_notification_round), + Icon(ZetaIcons.warning_outline_round), + Icon(ZetaIcons.warning_round), + Icon(ZetaIcons.block_round), + Icon(ZetaIcons.closed_caption_round), + Icon(ZetaIcons.fast_forward_round), + Icon(ZetaIcons.fast_rewind_round), + Icon(ZetaIcons.loop_round), + Icon(ZetaIcons.microphone_off_round), + Icon(ZetaIcons.microphone_outline_round), + Icon(ZetaIcons.microphone_round), + Icon(ZetaIcons.pause_circle_round), + Icon(ZetaIcons.pause_round), + Icon(ZetaIcons.play_circle_round), + Icon(ZetaIcons.play_outline_round), + Icon(ZetaIcons.play_round), + Icon(ZetaIcons.replay_round), + Icon(ZetaIcons.skip_next_round), + Icon(ZetaIcons.skip_previous_round), + Icon(ZetaIcons.stop_circle_round), + Icon(ZetaIcons.stop_round), + Icon(ZetaIcons.video_camera_round), + Icon(ZetaIcons.volume_down_round), + Icon(ZetaIcons.volume_mute_round), + Icon(ZetaIcons.volume_off_round), + Icon(ZetaIcons.volume_up_round), + Icon(ZetaIcons.add_call_round), + Icon(ZetaIcons.chat_bubble_outline_round), + Icon(ZetaIcons.chat_bubble_round), + Icon(ZetaIcons.conversation_round), + Icon(ZetaIcons.dialpad_round), + Icon(ZetaIcons.do_not_disturb_round), + Icon(ZetaIcons.dollar_round), + Icon(ZetaIcons.email_alt_round), + Icon(ZetaIcons.email_outline_round), + Icon(ZetaIcons.email_round), + Icon(ZetaIcons.end_call_round), + Icon(ZetaIcons.message_round), + Icon(ZetaIcons.person_search_round), + Icon(ZetaIcons.phone_bluetooth_speaker_round), + Icon(ZetaIcons.phone_in_talk_round), + Icon(ZetaIcons.phone_round), + Icon(ZetaIcons.priority_round), + Icon(ZetaIcons.qr_code_round), + Icon(ZetaIcons.qr_code_scan_round), + Icon(ZetaIcons.rss_feed_round), + Icon(ZetaIcons.sd_card_round), + Icon(ZetaIcons.sim_card_round), + Icon(ZetaIcons.sms_round), + Icon(ZetaIcons.sync_disabled_round), + Icon(ZetaIcons.sync_round), + Icon(ZetaIcons.add_box_round), + Icon(ZetaIcons.add_circle_outline_round), + Icon(ZetaIcons.add_circle_round), + Icon(ZetaIcons.add_round), + Icon(ZetaIcons.analysis_round), + Icon(ZetaIcons.android_round), + Icon(ZetaIcons.backspace_round), + Icon(ZetaIcons.block_content_round), + Icon(ZetaIcons.clear_round), + Icon(ZetaIcons.content_round), + Icon(ZetaIcons.copy_file_round), + Icon(ZetaIcons.create_round), + Icon(ZetaIcons.filter_list_round), + Icon(ZetaIcons.flag_round), + Icon(ZetaIcons.link_content_round), + Icon(ZetaIcons.mail_round), + Icon(ZetaIcons.push_pin_round), + Icon(ZetaIcons.redo_round), + Icon(ZetaIcons.remove_box_round), + Icon(ZetaIcons.remove_circle_outline_round), + Icon(ZetaIcons.remove_circle_round), + Icon(ZetaIcons.remove_round), + Icon(ZetaIcons.reply_round), + Icon(ZetaIcons.save_alt_round), + Icon(ZetaIcons.save_round), + Icon(ZetaIcons.send_round), + Icon(ZetaIcons.sort_round), + Icon(ZetaIcons.undo_round), + Icon(ZetaIcons.antenna_round), + Icon(ZetaIcons.battery_alert_round), + Icon(ZetaIcons.battery_charging_round), + Icon(ZetaIcons.battery_round), + Icon(ZetaIcons.bluetooth_disabled_round), + Icon(ZetaIcons.bluetooth_round), + Icon(ZetaIcons.bluetooth_searching_round), + Icon(ZetaIcons.brightness_round), + Icon(ZetaIcons.cellular_signal_round), + Icon(ZetaIcons.chain_round), + Icon(ZetaIcons.contrast_round), + Icon(ZetaIcons.dark_mode_round), + Icon(ZetaIcons.devices_round), + Icon(ZetaIcons.ethernet_round), + Icon(ZetaIcons.flight_mode_round), + Icon(ZetaIcons.hdmi_round), + Icon(ZetaIcons.light_mode_round), + Icon(ZetaIcons.location_point_round), + Icon(ZetaIcons.location_round), + Icon(ZetaIcons.mobile_friendly_round), + Icon(ZetaIcons.network_signal_round), + Icon(ZetaIcons.nfc_round), + Icon(ZetaIcons.night_round), + Icon(ZetaIcons.restart_alt_round), + Icon(ZetaIcons.screen_rotation_round), + Icon(ZetaIcons.uhf_rfid_round), + Icon(ZetaIcons.usb_alt_device_round), + Icon(ZetaIcons.usb_alt_round), + Icon(ZetaIcons.usb_round), + Icon(ZetaIcons.volte_round), + Icon(ZetaIcons.appgallery_round), + Icon(ZetaIcons.application_analytics_round), + Icon(ZetaIcons.asset_tracker_lite_round), + Icon(ZetaIcons.blood_bag_plus_round), + Icon(ZetaIcons.bluetooth_management_round), + Icon(ZetaIcons.browser_print_round), + Icon(ZetaIcons.cloud_connect_round), + Icon(ZetaIcons.data_wedge_round), + Icon(ZetaIcons.design_tools_round), + Icon(ZetaIcons.device_tracker_round), + Icon(ZetaIcons.direct_connect_round), + Icon(ZetaIcons.emdk_round), + Icon(ZetaIcons.enterprise_browser_round), + Icon(ZetaIcons.enterprise_connectors_round), + Icon(ZetaIcons.enterprise_keyboard_round), + Icon(ZetaIcons.gms_restricted_mode_round), + Icon(ZetaIcons.intelligent_document_capture_round), + Icon(ZetaIcons.label_plus_round), + Icon(ZetaIcons.life_guard_round), + Icon(ZetaIcons.link_os_round), + Icon(ZetaIcons.mdm_connectors_round), + Icon(ZetaIcons.mdm_toolkit_round), + Icon(ZetaIcons.mobility_dna_round), + Icon(ZetaIcons.mobility_security_round), + Icon(ZetaIcons.multi_code_data_formatting_round), + Icon(ZetaIcons.mx_round), + Icon(ZetaIcons.ocr_round), + Icon(ZetaIcons.oem_config_round), + Icon(ZetaIcons.pairing_solutions_round), + Icon(ZetaIcons.pdf_direct_round), + Icon(ZetaIcons.power_precision_round), + Icon(ZetaIcons.preferred_symbol_round), + Icon(ZetaIcons.print_secure_round), + Icon(ZetaIcons.print_station_round), + Icon(ZetaIcons.printer_profile_manager_round), + Icon(ZetaIcons.przm_round), + Icon(ZetaIcons.remote_control_round), + Icon(ZetaIcons.remote_diagnostics_round), + Icon(ZetaIcons.remote_management_round), + Icon(ZetaIcons.rx_round), + Icon(ZetaIcons.scan_and_pair_round), + Icon(ZetaIcons.scan_speed_analytics_round), + Icon(ZetaIcons.scan_to_connect_round), + Icon(ZetaIcons.scanner_control_application_round), + Icon(ZetaIcons.setting_tool_round), + Icon(ZetaIcons.simulscan_round), + Icon(ZetaIcons.smart_te_lite_round), + Icon(ZetaIcons.smart_te_round), + Icon(ZetaIcons.smart_tek_round), + Icon(ZetaIcons.smartdex_round), + Icon(ZetaIcons.stagenow_round), + Icon(ZetaIcons.swipe_assist_round), + Icon(ZetaIcons.tekspeech_pro_round), + Icon(ZetaIcons.virtual_devices_round), + Icon(ZetaIcons.virtual_tether_round), + Icon(ZetaIcons.visibility_services_round), + Icon(ZetaIcons.voice_wedge_round), + Icon(ZetaIcons.workforce_connect_round), + Icon(ZetaIcons.workstation_connect_round), + Icon(ZetaIcons.zebra_designer_round), + Icon(ZetaIcons.zebra_onecare_round), + Icon(ZetaIcons.zebra_setup_utility_round), + Icon(ZetaIcons.zero_touch_round), + Icon(ZetaIcons.align_center_round), + Icon(ZetaIcons.align_horizontal_center_round), + Icon(ZetaIcons.align_horizontal_left_round), + Icon(ZetaIcons.align_horizontal_right_round), + Icon(ZetaIcons.align_left_round), + Icon(ZetaIcons.align_right_round), + Icon(ZetaIcons.align_vertical_bottom_round), + Icon(ZetaIcons.align_vertical_center_round), + Icon(ZetaIcons.align_vertical_top_round), + Icon(ZetaIcons.attach_round), + Icon(ZetaIcons.bold_round), + Icon(ZetaIcons.bullet_list_round), + Icon(ZetaIcons.checklist_round), + Icon(ZetaIcons.color_fill_round), + Icon(ZetaIcons.distribute_horizontal_round), + Icon(ZetaIcons.distribute_vertical_round), + Icon(ZetaIcons.edit_border_round), + Icon(ZetaIcons.edit_round), + Icon(ZetaIcons.font_size_decrease_round), + Icon(ZetaIcons.font_size_increase_round), + Icon(ZetaIcons.format_shapes_round), + Icon(ZetaIcons.indent_decrease_round), + Icon(ZetaIcons.indent_increase_round), + Icon(ZetaIcons.italic_round), + Icon(ZetaIcons.justify_round), + Icon(ZetaIcons.line_spacing_round), + Icon(ZetaIcons.link_round), + Icon(ZetaIcons.no_color_round), + Icon(ZetaIcons.numbered_list_round), + Icon(ZetaIcons.strikethrough_round), + Icon(ZetaIcons.text_color_round), + Icon(ZetaIcons.type_round), + Icon(ZetaIcons.underline_round), + Icon(ZetaIcons.barcode_bluetooth_round), + Icon(ZetaIcons.barcode_done_round), + Icon(ZetaIcons.barcode_image_scan_round), + Icon(ZetaIcons.barcode_qr_code_round), + Icon(ZetaIcons.barcode_round), + Icon(ZetaIcons.barcode_scanner_down_round), + Icon(ZetaIcons.barcode_settings_round), + Icon(ZetaIcons.calculator_round), + Icon(ZetaIcons.card_orientation_round), + Icon(ZetaIcons.card_with_chip_round), + Icon(ZetaIcons.certificate_round), + Icon(ZetaIcons.choices_round), + Icon(ZetaIcons.contactless_pay_round), + Icon(ZetaIcons.credit_card_swipe_round), + Icon(ZetaIcons.eas_round), + Icon(ZetaIcons.enterprise_diagnostics_round), + Icon(ZetaIcons.environmental_round), + Icon(ZetaIcons.factory_round), + Icon(ZetaIcons.freezer_round), + Icon(ZetaIcons.issue_audit_round), + Icon(ZetaIcons.performance_round), + Icon(ZetaIcons.planogram_round), + Icon(ZetaIcons.productivity_apps_round), + Icon(ZetaIcons.receipt_round), + Icon(ZetaIcons.retail_round), + Icon(ZetaIcons.road_map_round), + Icon(ZetaIcons.rules_round), + Icon(ZetaIcons.scan_rate_round), + Icon(ZetaIcons.shape_recognition_round), + Icon(ZetaIcons.solutions_round), + Icon(ZetaIcons.steps_round), + Icon(ZetaIcons.strategy_round), + Icon(ZetaIcons.tap_to_pay_round), + Icon(ZetaIcons.zero_scale_round), + Icon(ZetaIcons.attachment_round), + Icon(ZetaIcons.cloud_done_round), + Icon(ZetaIcons.cloud_download_round), + Icon(ZetaIcons.cloud_off_round), + Icon(ZetaIcons.cloud_outline_round), + Icon(ZetaIcons.cloud_round), + Icon(ZetaIcons.cloud_upload_round), + Icon(ZetaIcons.create_new_folder_round), + Icon(ZetaIcons.doc_attach_round), + Icon(ZetaIcons.downloading_round), + Icon(ZetaIcons.file_download_round), + Icon(ZetaIcons.file_upload_round), + Icon(ZetaIcons.finished_download_round), + Icon(ZetaIcons.folder_outline_round), + Icon(ZetaIcons.folder_round), + Icon(ZetaIcons.grid_view_round), + Icon(ZetaIcons.jpg_attach_round), + Icon(ZetaIcons.pdf_attach_round), + Icon(ZetaIcons.png_attach_round), + Icon(ZetaIcons.ppt_attach_round), + Icon(ZetaIcons.shared_folder_round), + Icon(ZetaIcons.upload_file_round), + Icon(ZetaIcons.cast_connected_round), + Icon(ZetaIcons.cast_round), + Icon(ZetaIcons.desktop_round), + Icon(ZetaIcons.device_settings_round), + Icon(ZetaIcons.devices_ecosystem_round), + Icon(ZetaIcons.headphones_round), + Icon(ZetaIcons.keyboard_round), + Icon(ZetaIcons.laptop_round), + Icon(ZetaIcons.memory_round), + Icon(ZetaIcons.monitor_round), + Icon(ZetaIcons.phone_android_round), + Icon(ZetaIcons.phone_iphone_round), + Icon(ZetaIcons.phonelink_round), + Icon(ZetaIcons.printer_round), + Icon(ZetaIcons.scanner_round), + Icon(ZetaIcons.security_round), + Icon(ZetaIcons.smart_phone_round), + Icon(ZetaIcons.speaker_round), + Icon(ZetaIcons.tablet_mac_round), + Icon(ZetaIcons.tablet_round), + Icon(ZetaIcons.tv_round), + Icon(ZetaIcons.video_play_round), + Icon(ZetaIcons.watch_round), + Icon(ZetaIcons.adjustments_round), + Icon(ZetaIcons.auto_round), + Icon(ZetaIcons.awb_round), + Icon(ZetaIcons.camera_round), + Icon(ZetaIcons.camera_shutter_round), + Icon(ZetaIcons.contrast_image_round), + Icon(ZetaIcons.crop_round), + Icon(ZetaIcons.eye_dropper_round), + Icon(ZetaIcons.flip_camera_round), + Icon(ZetaIcons.grid_off_round), + Icon(ZetaIcons.grid_on_round), + Icon(ZetaIcons.hdr_round), + Icon(ZetaIcons.image_library_round), + Icon(ZetaIcons.image_round), + Icon(ZetaIcons.iso_round), + Icon(ZetaIcons.portrait_round), + Icon(ZetaIcons.pro_round), + Icon(ZetaIcons.rotate_left_round), + Icon(ZetaIcons.rotate_right_round), + Icon(ZetaIcons.slide_show_round), + Icon(ZetaIcons.straighten_round), + Icon(ZetaIcons.timer_round), + Icon(ZetaIcons.visibility_image_round), + Icon(ZetaIcons.visibility_off_image_round), + Icon(ZetaIcons.wb_image_round), + Icon(ZetaIcons.wb_round), + Icon(ZetaIcons.bus_round), + Icon(ZetaIcons.cafe_round), + Icon(ZetaIcons.car_round), + Icon(ZetaIcons.flight_round), + Icon(ZetaIcons.layers_round), + Icon(ZetaIcons.light_rail_train_round), + Icon(ZetaIcons.local_shipping_round), + Icon(ZetaIcons.map_round), + Icon(ZetaIcons.my_location_round), + Icon(ZetaIcons.navigation_round), + Icon(ZetaIcons.near_me_round), + Icon(ZetaIcons.offer_round), + Icon(ZetaIcons.place_round), + Icon(ZetaIcons.ship_round), + Icon(ZetaIcons.taxi_round), + Icon(ZetaIcons.train_round), + Icon(ZetaIcons.world_round), + Icon(ZetaIcons.zoom_in_map_round), + Icon(ZetaIcons.zoom_out_map_round), + Icon(ZetaIcons.apps_round), + Icon(ZetaIcons.arrow_back_round), + Icon(ZetaIcons.arrow_down_round), + Icon(ZetaIcons.arrow_forward_round), + Icon(ZetaIcons.arrow_up_round), + Icon(ZetaIcons.cancel_outline_round), + Icon(ZetaIcons.cancel_round), + Icon(ZetaIcons.caret_down_round), + Icon(ZetaIcons.caret_left_round), + Icon(ZetaIcons.caret_right_round), + Icon(ZetaIcons.caret_sort_round), + Icon(ZetaIcons.caret_up_round), + Icon(ZetaIcons.check_round), + Icon(ZetaIcons.chevron_left_round), + Icon(ZetaIcons.chevron_right_round), + Icon(ZetaIcons.close_round), + Icon(ZetaIcons.columns_round), + Icon(ZetaIcons.dashboard_round), + Icon(ZetaIcons.drop_down_circle_round), + Icon(ZetaIcons.expand_less_round), + Icon(ZetaIcons.expand_more_round), + Icon(ZetaIcons.first_page_round), + Icon(ZetaIcons.full_screen_exit_round), + Icon(ZetaIcons.full_screen_round), + Icon(ZetaIcons.hamburger_menu_navigation_rail_round), + Icon(ZetaIcons.hamburger_menu_round), + Icon(ZetaIcons.hamburger_menu_thick_round), + Icon(ZetaIcons.help_outline_round), + Icon(ZetaIcons.help_round), + Icon(ZetaIcons.last_page_round), + Icon(ZetaIcons.list_alt_round), + Icon(ZetaIcons.list_round), + Icon(ZetaIcons.more_horizontal_round), + Icon(ZetaIcons.more_vertical_round), + Icon(ZetaIcons.refresh_round), + Icon(ZetaIcons.unfold_less_round), + Icon(ZetaIcons.unfold_more_round), + Icon(ZetaIcons.add_group_round), + Icon(ZetaIcons.add_person_round), + Icon(ZetaIcons.bad_mood_round), + Icon(ZetaIcons.blog_round), + Icon(ZetaIcons.dislike_round), + Icon(ZetaIcons.facebook_round), + Icon(ZetaIcons.group_round), + Icon(ZetaIcons.groups_round), + Icon(ZetaIcons.happy_round), + Icon(ZetaIcons.instagram_round), + Icon(ZetaIcons.ios_share_round), + Icon(ZetaIcons.like_round), + Icon(ZetaIcons.linkedin_round), + Icon(ZetaIcons.medium_round), + Icon(ZetaIcons.notifications_active_round), + Icon(ZetaIcons.notifications_outline_round), + Icon(ZetaIcons.notifications_round), + Icon(ZetaIcons.person_outline_round), + Icon(ZetaIcons.person_round), + Icon(ZetaIcons.remove_group_round), + Icon(ZetaIcons.remove_person_round), + Icon(ZetaIcons.sad_round), + Icon(ZetaIcons.satisfied_round), + Icon(ZetaIcons.share_round), + Icon(ZetaIcons.switch_user_round), + Icon(ZetaIcons.twitter_round), + Icon(ZetaIcons.very_satisfied_round), + Icon(ZetaIcons.world_map_round), + Icon(ZetaIcons.youtube_round), + Icon(ZetaIcons.check_box_empty_round), + Icon(ZetaIcons.check_box_round), + Icon(ZetaIcons.indeterminate_check_box_round), + Icon(ZetaIcons.radio_button_checked_round), + Icon(ZetaIcons.radio_button_unchecked_round), + Icon(ZetaIcons.star_half_round), + Icon(ZetaIcons.star_outline_round), + Icon(ZetaIcons.star_round), + Icon(ZetaIcons.toggle_off_round), + Icon(ZetaIcons.toggle_on_round), ], ), - ), - ); - }, + const SizedBox(height: 20), + Text('Sharp', style: ZetaTextStyles.bodyLarge), + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + Icon(ZetaIcons.alarm_sharp), + Icon(ZetaIcons.ar_sharp), + Icon(ZetaIcons.bookmark_outline_sharp), + Icon(ZetaIcons.bookmark_sharp), + Icon(ZetaIcons.build_sharp), + Icon(ZetaIcons.cached_sharp), + Icon(ZetaIcons.calendar_3_day_sharp), + Icon(ZetaIcons.calendar_alt_1_sharp), + Icon(ZetaIcons.calendar_alt_2_sharp), + Icon(ZetaIcons.calendar_available_sharp), + Icon(ZetaIcons.calendar_cancel_sharp), + Icon(ZetaIcons.calendar_day_sharp), + Icon(ZetaIcons.calendar_edit_sharp), + Icon(ZetaIcons.calendar_monthly_alt_sharp), + Icon(ZetaIcons.calendar_monthly_sharp), + Icon(ZetaIcons.calendar_range_sharp), + Icon(ZetaIcons.calendar_sharp), + Icon(ZetaIcons.calendar_weekly_alt_sharp), + Icon(ZetaIcons.calendar_weekly_sharp), + Icon(ZetaIcons.calendar_yearly_sharp), + Icon(ZetaIcons.check_circle_outline_alt_sharp), + Icon(ZetaIcons.check_circle_outline_sharp), + Icon(ZetaIcons.check_circle_sharp), + Icon(ZetaIcons.check_mark_sharp), + Icon(ZetaIcons.clipboard_sharp), + Icon(ZetaIcons.clock_outline_sharp), + Icon(ZetaIcons.clock_sharp), + Icon(ZetaIcons.credit_card_sharp), + Icon(ZetaIcons.delete_forever_sharp), + Icon(ZetaIcons.delete_outline_sharp), + Icon(ZetaIcons.delete_sharp), + Icon(ZetaIcons.dislike_action_sharp), + Icon(ZetaIcons.document_sharp), + Icon(ZetaIcons.download_sharp), + Icon(ZetaIcons.filter_alt_sharp), + Icon(ZetaIcons.filter_sharp), + Icon(ZetaIcons.hand_sharp), + Icon(ZetaIcons.history_sharp), + Icon(ZetaIcons.home_sharp), + Icon(ZetaIcons.info_sharp), + Icon(ZetaIcons.label_sharp), + Icon(ZetaIcons.like_action_sharp), + Icon(ZetaIcons.lock_alt_sharp), + Icon(ZetaIcons.lock_sharp), + Icon(ZetaIcons.log_in_sharp), + Icon(ZetaIcons.log_out_sharp), + Icon(ZetaIcons.love_outline_sharp), + Icon(ZetaIcons.love_sharp), + Icon(ZetaIcons.open_in_full_sharp), + Icon(ZetaIcons.open_in_new_window_sharp), + Icon(ZetaIcons.pending_sharp), + Icon(ZetaIcons.pin_sharp), + Icon(ZetaIcons.price_sharp), + Icon(ZetaIcons.renew_sharp), + Icon(ZetaIcons.search_sharp), + Icon(ZetaIcons.security_check_sharp), + Icon(ZetaIcons.settings_sharp), + Icon(ZetaIcons.sync_action_sharp), + Icon(ZetaIcons.touch_sharp), + Icon(ZetaIcons.trending_down_sharp), + Icon(ZetaIcons.trending_up_sharp), + Icon(ZetaIcons.unlock_alt_sharp), + Icon(ZetaIcons.unlock_sharp), + Icon(ZetaIcons.update_sharp), + Icon(ZetaIcons.upload_sharp), + Icon(ZetaIcons.user_circle_sharp), + Icon(ZetaIcons.user_sharp), + Icon(ZetaIcons.user_settings_sharp), + Icon(ZetaIcons.verified_sharp), + Icon(ZetaIcons.visibility_off_sharp), + Icon(ZetaIcons.visibility_sharp), + Icon(ZetaIcons.world_action_sharp), + Icon(ZetaIcons.zoom_in_sharp), + Icon(ZetaIcons.zoom_out_sharp), + Icon(ZetaIcons.add_alert_sharp), + Icon(ZetaIcons.alert_sharp), + Icon(ZetaIcons.auto_delete_sharp), + Icon(ZetaIcons.error_outline_sharp), + Icon(ZetaIcons.error_sharp), + Icon(ZetaIcons.important_notification_sharp), + Icon(ZetaIcons.warning_outline_sharp), + Icon(ZetaIcons.warning_sharp), + Icon(ZetaIcons.block_sharp), + Icon(ZetaIcons.closed_caption_sharp), + Icon(ZetaIcons.fast_forward_sharp), + Icon(ZetaIcons.fast_rewind_sharp), + Icon(ZetaIcons.loop_sharp), + Icon(ZetaIcons.microphone_off_sharp), + Icon(ZetaIcons.microphone_outline_sharp), + Icon(ZetaIcons.microphone_sharp), + Icon(ZetaIcons.pause_circle_sharp), + Icon(ZetaIcons.pause_sharp), + Icon(ZetaIcons.play_circle_sharp), + Icon(ZetaIcons.play_outline_sharp), + Icon(ZetaIcons.play_sharp), + Icon(ZetaIcons.replay_sharp), + Icon(ZetaIcons.skip_next_sharp), + Icon(ZetaIcons.skip_previous_sharp), + Icon(ZetaIcons.stop_circle_sharp), + Icon(ZetaIcons.stop_sharp), + Icon(ZetaIcons.video_camera_sharp), + Icon(ZetaIcons.volume_down_sharp), + Icon(ZetaIcons.volume_mute_sharp), + Icon(ZetaIcons.volume_off_sharp), + Icon(ZetaIcons.volume_up_sharp), + Icon(ZetaIcons.add_call_sharp), + Icon(ZetaIcons.chat_bubble_outline_sharp), + Icon(ZetaIcons.chat_bubble_sharp), + Icon(ZetaIcons.conversation_sharp), + Icon(ZetaIcons.dialpad_sharp), + Icon(ZetaIcons.do_not_disturb_sharp), + Icon(ZetaIcons.dollar_sharp), + Icon(ZetaIcons.email_alt_sharp), + Icon(ZetaIcons.email_outline_sharp), + Icon(ZetaIcons.email_sharp), + Icon(ZetaIcons.end_call_sharp), + Icon(ZetaIcons.message_sharp), + Icon(ZetaIcons.person_search_sharp), + Icon(ZetaIcons.phone_bluetooth_speaker_sharp), + Icon(ZetaIcons.phone_in_talk_sharp), + Icon(ZetaIcons.phone_sharp), + Icon(ZetaIcons.priority_sharp), + Icon(ZetaIcons.qr_code_sharp), + Icon(ZetaIcons.qr_code_scan_sharp), + Icon(ZetaIcons.rss_feed_sharp), + Icon(ZetaIcons.sd_card_sharp), + Icon(ZetaIcons.sim_card_sharp), + Icon(ZetaIcons.sms_sharp), + Icon(ZetaIcons.sync_disabled_sharp), + Icon(ZetaIcons.sync_sharp), + Icon(ZetaIcons.add_box_sharp), + Icon(ZetaIcons.add_circle_outline_sharp), + Icon(ZetaIcons.add_circle_sharp), + Icon(ZetaIcons.add_sharp), + Icon(ZetaIcons.analysis_sharp), + Icon(ZetaIcons.android_sharp), + Icon(ZetaIcons.backspace_sharp), + Icon(ZetaIcons.block_content_sharp), + Icon(ZetaIcons.clear_sharp), + Icon(ZetaIcons.content_sharp), + Icon(ZetaIcons.copy_file_sharp), + Icon(ZetaIcons.create_sharp), + Icon(ZetaIcons.filter_list_sharp), + Icon(ZetaIcons.flag_sharp), + Icon(ZetaIcons.link_content_sharp), + Icon(ZetaIcons.mail_sharp), + Icon(ZetaIcons.push_pin_sharp), + Icon(ZetaIcons.redo_sharp), + Icon(ZetaIcons.remove_box_sharp), + Icon(ZetaIcons.remove_circle_outline_sharp), + Icon(ZetaIcons.remove_circle_sharp), + Icon(ZetaIcons.remove_sharp), + Icon(ZetaIcons.reply_sharp), + Icon(ZetaIcons.save_alt_sharp), + Icon(ZetaIcons.save_sharp), + Icon(ZetaIcons.send_sharp), + Icon(ZetaIcons.sort_sharp), + Icon(ZetaIcons.undo_sharp), + Icon(ZetaIcons.antenna_sharp), + Icon(ZetaIcons.battery_alert_sharp), + Icon(ZetaIcons.battery_charging_sharp), + Icon(ZetaIcons.battery_sharp), + Icon(ZetaIcons.bluetooth_disabled_sharp), + Icon(ZetaIcons.bluetooth_sharp), + Icon(ZetaIcons.bluetooth_searching_sharp), + Icon(ZetaIcons.brightness_sharp), + Icon(ZetaIcons.cellular_signal_sharp), + Icon(ZetaIcons.chain_sharp), + Icon(ZetaIcons.contrast_sharp), + Icon(ZetaIcons.dark_mode_sharp), + Icon(ZetaIcons.devices_sharp), + Icon(ZetaIcons.ethernet_sharp), + Icon(ZetaIcons.flight_mode_sharp), + Icon(ZetaIcons.hdmi_sharp), + Icon(ZetaIcons.light_mode_sharp), + Icon(ZetaIcons.location_point_sharp), + Icon(ZetaIcons.location_sharp), + Icon(ZetaIcons.mobile_friendly_sharp), + Icon(ZetaIcons.network_signal_sharp), + Icon(ZetaIcons.nfc_sharp), + Icon(ZetaIcons.night_sharp), + Icon(ZetaIcons.restart_alt_sharp), + Icon(ZetaIcons.screen_rotation_sharp), + Icon(ZetaIcons.uhf_rfid_sharp), + Icon(ZetaIcons.usb_alt_device_sharp), + Icon(ZetaIcons.usb_alt_sharp), + Icon(ZetaIcons.usb_sharp), + Icon(ZetaIcons.volte_sharp), + Icon(ZetaIcons.appgallery_sharp), + Icon(ZetaIcons.application_analytics_sharp), + Icon(ZetaIcons.asset_tracker_lite_sharp), + Icon(ZetaIcons.blood_bag_plus_sharp), + Icon(ZetaIcons.bluetooth_management_sharp), + Icon(ZetaIcons.browser_print_sharp), + Icon(ZetaIcons.cloud_connect_sharp), + Icon(ZetaIcons.data_wedge_sharp), + Icon(ZetaIcons.design_tools_sharp), + Icon(ZetaIcons.device_tracker_sharp), + Icon(ZetaIcons.direct_connect_sharp), + Icon(ZetaIcons.emdk_sharp), + Icon(ZetaIcons.enterprise_browser_sharp), + Icon(ZetaIcons.enterprise_connectors_sharp), + Icon(ZetaIcons.enterprise_keyboard_sharp), + Icon(ZetaIcons.gms_restricted_mode_sharp), + Icon(ZetaIcons.intelligent_document_capture_sharp), + Icon(ZetaIcons.label_plus_sharp), + Icon(ZetaIcons.life_guard_sharp), + Icon(ZetaIcons.link_os_sharp), + Icon(ZetaIcons.mdm_connectors_sharp), + Icon(ZetaIcons.mdm_toolkit_sharp), + Icon(ZetaIcons.mobility_dna_sharp), + Icon(ZetaIcons.mobility_security_sharp), + Icon(ZetaIcons.multi_code_data_formatting_sharp), + Icon(ZetaIcons.mx_sharp), + Icon(ZetaIcons.ocr_sharp), + Icon(ZetaIcons.oem_config_sharp), + Icon(ZetaIcons.pairing_solutions_sharp), + Icon(ZetaIcons.pdf_direct_sharp), + Icon(ZetaIcons.power_precision_sharp), + Icon(ZetaIcons.preferred_symbol_sharp), + Icon(ZetaIcons.print_secure_sharp), + Icon(ZetaIcons.print_station_sharp), + Icon(ZetaIcons.printer_profile_manager_sharp), + Icon(ZetaIcons.przm_sharp), + Icon(ZetaIcons.remote_control_sharp), + Icon(ZetaIcons.remote_diagnostics_sharp), + Icon(ZetaIcons.remote_management_sharp), + Icon(ZetaIcons.rx_sharp), + Icon(ZetaIcons.scan_and_pair_sharp), + Icon(ZetaIcons.scan_speed_analytics_sharp), + Icon(ZetaIcons.scan_to_connect_sharp), + Icon(ZetaIcons.scanner_control_application_sharp), + Icon(ZetaIcons.setting_tool_sharp), + Icon(ZetaIcons.simulscan_sharp), + Icon(ZetaIcons.smart_te_lite_sharp), + Icon(ZetaIcons.smart_te_sharp), + Icon(ZetaIcons.smart_tek_sharp), + Icon(ZetaIcons.smartdex_sharp), + Icon(ZetaIcons.stagenow_sharp), + Icon(ZetaIcons.swipe_assist_sharp), + Icon(ZetaIcons.tekspeech_pro_sharp), + Icon(ZetaIcons.virtual_devices_sharp), + Icon(ZetaIcons.virtual_tether_sharp), + Icon(ZetaIcons.visibility_services_sharp), + Icon(ZetaIcons.voice_wedge_sharp), + Icon(ZetaIcons.workforce_connect_sharp), + Icon(ZetaIcons.workstation_connect_sharp), + Icon(ZetaIcons.zebra_designer_sharp), + Icon(ZetaIcons.zebra_onecare_sharp), + Icon(ZetaIcons.zebra_setup_utility_sharp), + Icon(ZetaIcons.zero_touch_sharp), + Icon(ZetaIcons.align_center_sharp), + Icon(ZetaIcons.align_horizontal_center_sharp), + Icon(ZetaIcons.align_horizontal_left_sharp), + Icon(ZetaIcons.align_horizontal_right_sharp), + Icon(ZetaIcons.align_left_sharp), + Icon(ZetaIcons.align_right_sharp), + Icon(ZetaIcons.align_vertical_bottom_sharp), + Icon(ZetaIcons.align_vertical_center_sharp), + Icon(ZetaIcons.align_vertical_top_sharp), + Icon(ZetaIcons.attach_sharp), + Icon(ZetaIcons.bold_sharp), + Icon(ZetaIcons.bullet_list_sharp), + Icon(ZetaIcons.checklist_sharp), + Icon(ZetaIcons.color_fill_sharp), + Icon(ZetaIcons.distribute_horizontal_sharp), + Icon(ZetaIcons.distribute_vertical_sharp), + Icon(ZetaIcons.edit_border_sharp), + Icon(ZetaIcons.edit_sharp), + Icon(ZetaIcons.font_size_decrease_sharp), + Icon(ZetaIcons.font_size_increase_sharp), + Icon(ZetaIcons.format_shapes_sharp), + Icon(ZetaIcons.indent_decrease_sharp), + Icon(ZetaIcons.indent_increase_sharp), + Icon(ZetaIcons.italic_sharp), + Icon(ZetaIcons.justify_sharp), + Icon(ZetaIcons.line_spacing_sharp), + Icon(ZetaIcons.link_sharp), + Icon(ZetaIcons.no_color_sharp), + Icon(ZetaIcons.numbered_list_sharp), + Icon(ZetaIcons.strikethrough_sharp), + Icon(ZetaIcons.text_color_sharp), + Icon(ZetaIcons.type_sharp), + Icon(ZetaIcons.underline_sharp), + Icon(ZetaIcons.barcode_bluetooth_sharp), + Icon(ZetaIcons.barcode_done_sharp), + Icon(ZetaIcons.barcode_image_scan_sharp), + Icon(ZetaIcons.barcode_qr_code_sharp), + Icon(ZetaIcons.barcode_sharp), + Icon(ZetaIcons.barcode_scanner_down_sharp), + Icon(ZetaIcons.barcode_settings_sharp), + Icon(ZetaIcons.calculator_sharp), + Icon(ZetaIcons.card_orientation_sharp), + Icon(ZetaIcons.card_with_chip_sharp), + Icon(ZetaIcons.certificate_sharp), + Icon(ZetaIcons.choices_sharp), + Icon(ZetaIcons.contactless_pay_sharp), + Icon(ZetaIcons.credit_card_swipe_sharp), + Icon(ZetaIcons.eas_sharp), + Icon(ZetaIcons.enterprise_diagnostics_sharp), + Icon(ZetaIcons.environmental_sharp), + Icon(ZetaIcons.factory_sharp), + Icon(ZetaIcons.freezer_sharp), + Icon(ZetaIcons.issue_audit_sharp), + Icon(ZetaIcons.performance_sharp), + Icon(ZetaIcons.planogram_sharp), + Icon(ZetaIcons.productivity_apps_sharp), + Icon(ZetaIcons.receipt_sharp), + Icon(ZetaIcons.retail_sharp), + Icon(ZetaIcons.road_map_sharp), + Icon(ZetaIcons.rules_sharp), + Icon(ZetaIcons.scan_rate_sharp), + Icon(ZetaIcons.shape_recognition_sharp), + Icon(ZetaIcons.solutions_sharp), + Icon(ZetaIcons.steps_sharp), + Icon(ZetaIcons.strategy_sharp), + Icon(ZetaIcons.tap_to_pay_sharp), + Icon(ZetaIcons.zero_scale_sharp), + Icon(ZetaIcons.attachment_sharp), + Icon(ZetaIcons.cloud_done_sharp), + Icon(ZetaIcons.cloud_download_sharp), + Icon(ZetaIcons.cloud_off_sharp), + Icon(ZetaIcons.cloud_outline_sharp), + Icon(ZetaIcons.cloud_sharp), + Icon(ZetaIcons.cloud_upload_sharp), + Icon(ZetaIcons.create_new_folder_sharp), + Icon(ZetaIcons.doc_attach_sharp), + Icon(ZetaIcons.downloading_sharp), + Icon(ZetaIcons.file_download_sharp), + Icon(ZetaIcons.file_upload_sharp), + Icon(ZetaIcons.finished_download_sharp), + Icon(ZetaIcons.folder_outline_sharp), + Icon(ZetaIcons.folder_sharp), + Icon(ZetaIcons.grid_view_sharp), + Icon(ZetaIcons.jpg_attach_sharp), + Icon(ZetaIcons.pdf_attach_sharp), + Icon(ZetaIcons.png_attach_sharp), + Icon(ZetaIcons.ppt_attach_sharp), + Icon(ZetaIcons.shared_folder_sharp), + Icon(ZetaIcons.upload_file_sharp), + Icon(ZetaIcons.cast_connected_sharp), + Icon(ZetaIcons.cast_sharp), + Icon(ZetaIcons.desktop_sharp), + Icon(ZetaIcons.device_settings_sharp), + Icon(ZetaIcons.devices_ecosystem_sharp), + Icon(ZetaIcons.headphones_sharp), + Icon(ZetaIcons.keyboard_sharp), + Icon(ZetaIcons.laptop_sharp), + Icon(ZetaIcons.memory_sharp), + Icon(ZetaIcons.monitor_sharp), + Icon(ZetaIcons.phone_android_sharp), + Icon(ZetaIcons.phone_iphone_sharp), + Icon(ZetaIcons.phonelink_sharp), + Icon(ZetaIcons.printer_sharp), + Icon(ZetaIcons.scanner_sharp), + Icon(ZetaIcons.security_sharp), + Icon(ZetaIcons.smart_phone_sharp), + Icon(ZetaIcons.speaker_sharp), + Icon(ZetaIcons.tablet_mac_sharp), + Icon(ZetaIcons.tablet_sharp), + Icon(ZetaIcons.tv_sharp), + Icon(ZetaIcons.video_play_sharp), + Icon(ZetaIcons.watch_sharp), + Icon(ZetaIcons.adjustments_sharp), + Icon(ZetaIcons.auto_sharp), + Icon(ZetaIcons.awb_sharp), + Icon(ZetaIcons.camera_sharp), + Icon(ZetaIcons.camera_shutter_sharp), + Icon(ZetaIcons.contrast_image_sharp), + Icon(ZetaIcons.crop_sharp), + Icon(ZetaIcons.eye_dropper_sharp), + Icon(ZetaIcons.flip_camera_sharp), + Icon(ZetaIcons.grid_off_sharp), + Icon(ZetaIcons.grid_on_sharp), + Icon(ZetaIcons.hdr_sharp), + Icon(ZetaIcons.image_library_sharp), + Icon(ZetaIcons.image_sharp), + Icon(ZetaIcons.iso_sharp), + Icon(ZetaIcons.portrait_sharp), + Icon(ZetaIcons.pro_sharp), + Icon(ZetaIcons.rotate_left_sharp), + Icon(ZetaIcons.rotate_right_sharp), + Icon(ZetaIcons.slide_show_sharp), + Icon(ZetaIcons.straighten_sharp), + Icon(ZetaIcons.timer_sharp), + Icon(ZetaIcons.visibility_image_sharp), + Icon(ZetaIcons.visibility_off_image_sharp), + Icon(ZetaIcons.wb_image_sharp), + Icon(ZetaIcons.wb_sharp), + Icon(ZetaIcons.bus_sharp), + Icon(ZetaIcons.cafe_sharp), + Icon(ZetaIcons.car_sharp), + Icon(ZetaIcons.flight_sharp), + Icon(ZetaIcons.layers_sharp), + Icon(ZetaIcons.light_rail_train_sharp), + Icon(ZetaIcons.local_shipping_sharp), + Icon(ZetaIcons.map_sharp), + Icon(ZetaIcons.my_location_sharp), + Icon(ZetaIcons.navigation_sharp), + Icon(ZetaIcons.near_me_sharp), + Icon(ZetaIcons.offer_sharp), + Icon(ZetaIcons.place_sharp), + Icon(ZetaIcons.ship_sharp), + Icon(ZetaIcons.taxi_sharp), + Icon(ZetaIcons.train_sharp), + Icon(ZetaIcons.world_sharp), + Icon(ZetaIcons.zoom_in_map_sharp), + Icon(ZetaIcons.zoom_out_map_sharp), + Icon(ZetaIcons.apps_sharp), + Icon(ZetaIcons.arrow_back_sharp), + Icon(ZetaIcons.arrow_down_sharp), + Icon(ZetaIcons.arrow_forward_sharp), + Icon(ZetaIcons.arrow_up_sharp), + Icon(ZetaIcons.cancel_outline_sharp), + Icon(ZetaIcons.cancel_sharp), + Icon(ZetaIcons.caret_down_sharp), + Icon(ZetaIcons.caret_left_sharp), + Icon(ZetaIcons.caret_right_sharp), + Icon(ZetaIcons.caret_sort_sharp), + Icon(ZetaIcons.caret_up_sharp), + Icon(ZetaIcons.check_sharp), + Icon(ZetaIcons.chevron_left_sharp), + Icon(ZetaIcons.chevron_right_sharp), + Icon(ZetaIcons.close_sharp), + Icon(ZetaIcons.columns_sharp), + Icon(ZetaIcons.dashboard_sharp), + Icon(ZetaIcons.drop_down_circle_sharp), + Icon(ZetaIcons.expand_less_sharp), + Icon(ZetaIcons.expand_more_sharp), + Icon(ZetaIcons.first_page_sharp), + Icon(ZetaIcons.full_screen_exit_sharp), + Icon(ZetaIcons.full_screen_sharp), + Icon(ZetaIcons.hamburger_menu_navigation_rail_sharp), + Icon(ZetaIcons.hamburger_menu_sharp), + Icon(ZetaIcons.hamburger_menu_thick_sharp), + Icon(ZetaIcons.help_outline_sharp), + Icon(ZetaIcons.help_sharp), + Icon(ZetaIcons.last_page_sharp), + Icon(ZetaIcons.list_alt_sharp), + Icon(ZetaIcons.list_sharp), + Icon(ZetaIcons.more_horizontal_sharp), + Icon(ZetaIcons.more_vertical_sharp), + Icon(ZetaIcons.refresh_sharp), + Icon(ZetaIcons.unfold_less_sharp), + Icon(ZetaIcons.unfold_more_sharp), + Icon(ZetaIcons.add_group_sharp), + Icon(ZetaIcons.add_person_sharp), + Icon(ZetaIcons.bad_mood_sharp), + Icon(ZetaIcons.blog_sharp), + Icon(ZetaIcons.dislike_sharp), + Icon(ZetaIcons.facebook_sharp), + Icon(ZetaIcons.group_sharp), + Icon(ZetaIcons.groups_sharp), + Icon(ZetaIcons.happy_sharp), + Icon(ZetaIcons.instagram_sharp), + Icon(ZetaIcons.ios_share_sharp), + Icon(ZetaIcons.like_sharp), + Icon(ZetaIcons.linkedin_sharp), + Icon(ZetaIcons.medium_sharp), + Icon(ZetaIcons.notifications_active_sharp), + Icon(ZetaIcons.notifications_outline_sharp), + Icon(ZetaIcons.notifications_sharp), + Icon(ZetaIcons.person_outline_sharp), + Icon(ZetaIcons.person_sharp), + Icon(ZetaIcons.remove_group_sharp), + Icon(ZetaIcons.remove_person_sharp), + Icon(ZetaIcons.sad_sharp), + Icon(ZetaIcons.satisfied_sharp), + Icon(ZetaIcons.share_sharp), + Icon(ZetaIcons.switch_user_sharp), + Icon(ZetaIcons.twitter_sharp), + Icon(ZetaIcons.very_satisfied_sharp), + Icon(ZetaIcons.world_map_sharp), + Icon(ZetaIcons.youtube_sharp), + Icon(ZetaIcons.check_box_empty_sharp), + Icon(ZetaIcons.check_box_sharp), + Icon(ZetaIcons.indeterminate_check_box_sharp), + Icon(ZetaIcons.radio_button_checked_sharp), + Icon(ZetaIcons.radio_button_unchecked_sharp), + Icon(ZetaIcons.star_half_sharp), + Icon(ZetaIcons.star_outline_sharp), + Icon(ZetaIcons.star_sharp), + Icon(ZetaIcons.toggle_off_sharp), + Icon(ZetaIcons.toggle_on_sharp), + ], + ), + ], + ), + ), ); } } diff --git a/example/lib/pages/components/accordion_example.dart b/example/lib/pages/components/accordion_example.dart index 7887683a..b23587c8 100644 --- a/example/lib/pages/components/accordion_example.dart +++ b/example/lib/pages/components/accordion_example.dart @@ -9,86 +9,85 @@ class AccordionExample extends StatelessWidget { @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: AccordionExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(ZetaSpacing.s), - child: Column( - children: [ - Text('Rounded Divider'), - const SizedBox(height: 20), - ZetaAccordion( - children: [ - ZetaAccordionSection( - title: Text('Title Default Enabled'), - body: Column( - children: [ - ListTile(title: Text('List Item')), - ListTile(title: Text('List Item')), - ListTile(title: Text('List Item')), - ], - ), - ), - ZetaAccordionSection(disabled: true, title: Text('Title Default Disabled'), body: Text('...')), - ], - ), - const SizedBox(height: 40), - Text('Rounded Contained'), - const SizedBox(height: 20), - ZetaAccordion( - contained: true, - children: [ - ZetaAccordionSection( - title: Text('Title Contained Enabled'), - body: Column( - children: [ - ListTile(title: Text('List Item')), - ListTile(title: Text('List Item')), - ListTile(title: Text('List Item')), - ], - ), - ), - ZetaAccordionSection(disabled: true, title: Text('Title Contained Disabled'), body: Text('...')), - ], - ), - const SizedBox(height: 40), - Text('Sharp Divider'), - const SizedBox(height: 20), - ZetaAccordion( - contained: false, - rounded: false, - children: [ - ZetaAccordionSection( - title: Text('Title Contained Sharp Enabled'), - body: Center(child: Icon(Icons.image_outlined, size: 300)), - ), - ZetaAccordionSection( - disabled: true, - title: Text('Title Contained Sharp Disabled'), - body: Text('...'), - ), - ], - ), - Text('Sharp Contained'), - const SizedBox(height: 20), - ZetaAccordion( - contained: true, - rounded: false, - children: [ - ZetaAccordionSection( - title: Text('Title'), - body: Center(child: Icon(Icons.image_outlined, size: 300)), - ), - ZetaAccordionSection(disabled: true, title: Text('Title'), body: Text('...')), - ], - ), - ], + return ExampleScaffold( + name: AccordionExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(ZetaSpacing.s), + child: Column( + children: [ + Text('Rounded Divider'), + const SizedBox(height: 20), + ZetaAccordion( + title: 'title', + child: Column( + children: [ + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ], + ), ), - ), - ); - }, + ZetaAccordion(title: 'title'), + const SizedBox(height: 40), + Text('Rounded Contained'), + const SizedBox(height: 20), + ZetaAccordion( + contained: true, + title: 'title', + child: Column( + children: [ + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ], + ), + ), + ZetaAccordion( + contained: true, + title: 'title', + ), + const SizedBox(height: 40), + Text('Sharp Divider'), + const SizedBox(height: 20), + ZetaAccordion( + contained: false, + title: 'title', + rounded: false, + child: Column( + children: [ + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ], + ), + ), + ZetaAccordion( + contained: false, + title: 'title', + rounded: false, + ), + Text('Sharp Contained'), + const SizedBox(height: 20), + ZetaAccordion( + contained: true, + title: 'title', + rounded: false, + child: Column( + children: [ + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ListTile(title: Text('List Item')), + ], + ), + ), + ZetaAccordion( + contained: true, + title: 'title', + rounded: false, + ), + ].divide(const SizedBox.square(dimension: 10)).toList(), + ), + ), ); } } diff --git a/example/lib/pages/components/avatar_example.dart b/example/lib/pages/components/avatar_example.dart index 7b210148..39f42a8f 100644 --- a/example/lib/pages/components/avatar_example.dart +++ b/example/lib/pages/components/avatar_example.dart @@ -1,3 +1,4 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; @@ -9,530 +10,586 @@ class AvatarExample extends StatelessWidget { @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: AvatarExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(ZetaSpacing.s), - child: Column( + final Widget image = CachedNetworkImage( + imageUrl: "https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg", + placeholder: (context, url) => Icon(ZetaIcons.user_round), + errorWidget: (context, url, error) => Icon(Icons.error), + fit: BoxFit.cover, + ); + + return ExampleScaffold( + name: AvatarExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(ZetaSpacing.s), + child: Column( + children: [ + Column( children: [ - Column( + Text( + 'ZetaAvatar.image', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( children: [ - Text( - 'ZetaAvatar.image', - style: TextStyle(fontWeight: FontWeight.bold), + Column( + children: ZetaAvatarSize.values.map((size) { + final height = size.pixelSize; + final padding = (height - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size); - final padding = (ZetaAvatar.getSizePixels(size) - 14) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image(size: size), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + borderColor: Zeta.of(context).colors.green, ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image(size: size), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + image: image, + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + borderColor: Zeta.of(context).colors.green, + image: image, + ), + const SizedBox(height: 20), + ], + )) + .toList(), ), ], ), - Column( + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.initials', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( children: [ - Text( - 'ZetaAvatar.initials', - style: TextStyle(fontWeight: FontWeight.bold), + Column( + children: ZetaAvatarSize.values.map((size) { + final height = size.pixelSize; + final padding = (height - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + ), + const SizedBox(height: 20), + ], + )) + .toList(), ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size); - final padding = (ZetaAvatar.getSizePixels(size) - 14) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), + const SizedBox(width: 15), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + borderColor: Zeta.of(context).colors.green, ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - initials: 'AB', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 15), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - name: 'Antony Brothers', - showStatus: true, - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], + const SizedBox(height: 20), + ], + )) + .toList(), ), ], ), - Column( + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.image with badge', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( children: [ - Text( - 'ZetaAvatar.image with badge', - style: TextStyle(fontWeight: FontWeight.bold), + Column( + children: ZetaAvatarSize.values.map((size) { + final height = size.pixelSize; + final padding = (height - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size) + 6; - final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + upperBadge: ZetaIndicator.notification(value: 3), ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + borderColor: Zeta.of(context).colors.green, + upperBadge: ZetaIndicator.notification(value: 3), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + upperBadge: ZetaIndicator.notification(value: 3), + image: image, + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + borderColor: Zeta.of(context).colors.green, + upperBadge: ZetaIndicator.notification(value: 3), + image: image, + ), + const SizedBox(height: 20), + ], + )) + .toList(), ), ], ), - Column( + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.initials with badge', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( children: [ - Text( - 'ZetaAvatar.initials with badge', - style: TextStyle(fontWeight: FontWeight.bold), + Column( + children: ZetaAvatarSize.values.map((size) { + final height = size.pixelSize; + final padding = (height - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size) + 6; - final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + upperBadge: ZetaIndicator.notification(value: 3), ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - initials: 'AB', - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - name: 'Antony Brothers', - showStatus: true, - badge: ZetaIndicator.notification( - value: 3, - size: _getBadgeSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + borderColor: Zeta.of(context).colors.green, + upperBadge: ZetaIndicator.notification(value: 3), + ), + const SizedBox(height: 20), + ], + )) + .toList(), ), ], ), - Column( + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.image with special status', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( children: [ - Text( - 'ZetaAvatar.image with special status', - style: TextStyle(fontWeight: FontWeight.bold), + Column( + children: ZetaAvatarSize.values.map((size) { + final height = size.pixelSize; + final padding = (height - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + lowerBadge: ZetaIndicator.icon(), + ), + const SizedBox(height: 20), + ], + )) + .toList(), ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size) + 6; - final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + borderColor: Zeta.of(context).colors.green, + lowerBadge: ZetaIndicator.icon(), ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.image( - size: size, - showStatus: true, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - imageUrl: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + lowerBadge: ZetaIndicator.icon(), + image: image, + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + borderColor: Zeta.of(context).colors.green, + lowerBadge: ZetaIndicator.icon(), + image: image, + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + ], + ), + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar.initials with special status', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( + children: [ + Column( + children: ZetaAvatarSize.values.map((size) { + final height = size.pixelSize; + final padding = (height - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + lowerBadge: ZetaIndicator.icon(), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + borderColor: Zeta.of(context).colors.green, + lowerBadge: ZetaIndicator.icon(), + ), + const SizedBox(height: 20), + ], + )) + .toList(), ), ], ), - Column( + ], + ), + Column( + children: [ + Text( + 'ZetaAvatar with notification badge and status badge', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Row( children: [ - Text( - 'ZetaAvatar.initials with special status', - style: TextStyle(fontWeight: FontWeight.bold), + Column( + children: ZetaAvatarSize.values.map((size) { + final height = size.pixelSize; + final padding = (height - 14) / 2; + return Column( + children: [ + SizedBox( + height: height, + child: Padding( + padding: EdgeInsets.only(top: padding), + child: Text(size.name.toUpperCase()), + ), + ), + const SizedBox(height: 20), + ], + ); + }).toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + image: image, + upperBadge: ZetaIndicator.notification(value: 3), + lowerBadge: ZetaIndicator.icon(), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.image( + size: size, + image: image, + borderColor: Zeta.of(context).colors.green, + upperBadge: ZetaIndicator.notification(value: 3), + lowerBadge: ZetaIndicator.icon(), + ), + const SizedBox(height: 20), + ], + )) + .toList(), + ), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + upperBadge: ZetaIndicator.notification(value: 3), + lowerBadge: ZetaIndicator.icon(), + ), + const SizedBox(height: 20), + ], + )) + .toList(), ), - const SizedBox(height: 15), - Row( - children: [ - Column( - children: ZetaAvatarSize.values.map((size) { - final height = ZetaAvatar.getSizePixels(size) + 6; - final padding = (ZetaAvatar.getSizePixels(size) - 8) / 2; - return Column( - children: [ - SizedBox( - height: height, - child: Padding( - padding: EdgeInsets.only(top: padding), - child: Text(size.name.toUpperCase()), + const SizedBox(width: 12), + Column( + children: ZetaAvatarSize.values + .map((size) => Column( + children: [ + ZetaAvatar.initials( + size: size, + initials: 'AB', + borderColor: Zeta.of(context).colors.green, + upperBadge: ZetaIndicator.notification(value: 3), + lowerBadge: ZetaIndicator.icon(), ), - ), - const SizedBox(height: 20), - ], - ); - }).toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - initials: 'AB', - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - const SizedBox(width: 12), - Column( - children: ZetaAvatarSize.values - .map((size) => Column( - children: [ - ZetaAvatar.initials( - size: size, - name: 'Antony Brothers', - showStatus: true, - specialStatus: ZetaIndicator.icon( - size: _getSpecialStatusSize(size), - ), - ), - const SizedBox(height: 20), - ], - )) - .toList(), - ), - ], + const SizedBox(height: 20), + ], + )) + .toList(), ), ], ), - ].divide(const SizedBox(height: ZetaSpacing.x6)).toList(), + ], ), - ), - ); - }, + ].divide(const SizedBox(height: ZetaSpacing.x6)).toList(), + ), + ), ); } +} - static ZetaIndicatorSize _getBadgeSize(ZetaAvatarSize size) { - switch (size) { - case ZetaAvatarSize.xl: - return ZetaIndicatorSize.large; - case ZetaAvatarSize.l: - return ZetaIndicatorSize.large; - case ZetaAvatarSize.m: - return ZetaIndicatorSize.large; - case ZetaAvatarSize.s: - return ZetaIndicatorSize.medium; - case ZetaAvatarSize.xs: - return ZetaIndicatorSize.small; - } - } - - static ZetaIndicatorSize _getSpecialStatusSize(ZetaAvatarSize size) { - switch (size) { +extension on ZetaAvatarSize { + double get pixelSize { + switch (this) { case ZetaAvatarSize.xl: - return ZetaIndicatorSize.large; + return ZetaSpacing.x16; case ZetaAvatarSize.l: - return ZetaIndicatorSize.medium; + return ZetaSpacing.x12; case ZetaAvatarSize.m: - return ZetaIndicatorSize.medium; + return ZetaSpacing.x10; case ZetaAvatarSize.s: - return ZetaIndicatorSize.medium; + return ZetaSpacing.x8; case ZetaAvatarSize.xs: - return ZetaIndicatorSize.small; + return ZetaSpacing.x6; } } } diff --git a/example/lib/pages/components/badges_example.dart b/example/lib/pages/components/badges_example.dart index 919e3a44..76d28534 100644 --- a/example/lib/pages/components/badges_example.dart +++ b/example/lib/pages/components/badges_example.dart @@ -51,7 +51,7 @@ class _DividingText extends StatelessWidget { class _StatusLabel extends StatelessWidget { const _StatusLabel(); - Widget statusLabelExampleRow(ZetaWidgetStatus type, {ZetaWidgetColor? colors}) { + Widget statusLabelExampleRow(ZetaWidgetStatus type) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, @@ -143,15 +143,15 @@ class _Indicators extends StatelessWidget { Row( children: [ ZetaIndicator.icon(), - ZetaIndicator.icon(size: ZetaIndicatorSize.medium), - ZetaIndicator.icon(size: ZetaIndicatorSize.small), + ZetaIndicator.icon(size: ZetaWidgetSize.medium), + ZetaIndicator.icon(size: ZetaWidgetSize.small), ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ), Row( children: [ - ZetaIndicator.icon(inverseBorder: true), - ZetaIndicator.icon(size: ZetaIndicatorSize.medium, inverseBorder: true), - ZetaIndicator.icon(size: ZetaIndicatorSize.small, inverseBorder: true), + ZetaIndicator.icon(inverse: true), + ZetaIndicator.icon(size: ZetaWidgetSize.medium, inverse: true), + ZetaIndicator.icon(size: ZetaWidgetSize.small, inverse: true), ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ), ].divide(const SizedBox.square(dimension: ZetaSpacing.xs)).toList(), @@ -175,15 +175,15 @@ class _Indicators extends StatelessWidget { Row( children: [ ZetaIndicator.notification(value: 3), - ZetaIndicator.notification(size: ZetaIndicatorSize.medium, value: 3), - ZetaIndicator.notification(size: ZetaIndicatorSize.small), + ZetaIndicator.notification(size: ZetaWidgetSize.medium, value: 3), + ZetaIndicator.notification(size: ZetaWidgetSize.small), ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ), Row( children: [ - ZetaIndicator.notification(value: 3, inverseBorder: true), - ZetaIndicator.notification(size: ZetaIndicatorSize.medium, value: 3, inverseBorder: true), - ZetaIndicator.notification(size: ZetaIndicatorSize.small, inverseBorder: true), + ZetaIndicator.notification(value: 3, inverse: true), + ZetaIndicator.notification(size: ZetaWidgetSize.medium, value: 3, inverse: true), + ZetaIndicator.notification(size: ZetaWidgetSize.small, inverse: true), ].divide(const SizedBox.square(dimension: ZetaSpacing.m)).toList(), ), ].divide(const SizedBox.square(dimension: ZetaSpacing.s)).toList(), diff --git a/example/lib/pages/components/banner_example.dart b/example/lib/pages/components/banner_example.dart index 3a838897..b6513599 100644 --- a/example/lib/pages/components/banner_example.dart +++ b/example/lib/pages/components/banner_example.dart @@ -134,39 +134,33 @@ class BannerExample extends StatelessWidget { Text('In-Page Banner', style: ZetaTextStyles.displayMedium), ZetaInPageBanner( content: Text(_content), - onClose: () {}, - severity: ZetaWidgetStatus.info, - showIconClose: false, + status: ZetaWidgetStatus.info, ), ZetaInPageBanner( content: Text(_content), onClose: () {}, - severity: ZetaWidgetStatus.positive, - showIconClose: true, + status: ZetaWidgetStatus.positive, title: 'Banner Title', rounded: false, ), ZetaInPageBanner( content: Text(_content), onClose: () {}, - severity: ZetaWidgetStatus.warning, - showIconClose: true, + status: ZetaWidgetStatus.warning, title: 'Banner Title', actions: [ZetaButton(label: 'Button', onPressed: () {})], ), ZetaInPageBanner( content: Text(_content), onClose: () {}, - severity: ZetaWidgetStatus.negative, - showIconClose: true, + status: ZetaWidgetStatus.negative, title: 'Banner Title Banner Title Banner Title Banner Title', rounded: false, ), ZetaInPageBanner( content: Text(_content), onClose: () {}, - severity: ZetaWidgetStatus.neutral, - showIconClose: true, + status: ZetaWidgetStatus.neutral, title: 'Banner Title', ) ].divide(const SizedBox(height: 10)).toList(), @@ -183,7 +177,6 @@ class BannerExample extends StatelessWidget { Column buildExampleBannerColumn( ZetaWidgetStatus status, { - ZetaWidgetColor? customColors, bool rounded = true, IconData? customIcon, }) { @@ -195,8 +188,7 @@ class BannerExample extends StatelessWidget { content: Text(_content), onClose: () {}, rounded: rounded, - severity: status, - showIconClose: true, + status: status, title: 'Banner Title', customIcon: customIcon, ), diff --git a/example/lib/pages/components/bottom_sheet.dart b/example/lib/pages/components/bottom_sheet.dart deleted file mode 100644 index 92606256..00000000 --- a/example/lib/pages/components/bottom_sheet.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_example/widgets.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -class BottomSheetExample extends StatelessWidget { - static const String name = 'BottomSheet'; - - const BottomSheetExample({super.key}); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: BottomSheetExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(ZetaSpacing.s), - child: Column( - children: [ - ZetaMenuItem.horizontal( - label: Text('Grid'), - onTap: () { - showModalBottomSheet( - context: context, - builder: (BuildContext context) { - return ZetaBottomSheet( - title: 'Bottom Sheet', - titleAlignment: Alignment.centerLeft, - body: Wrap( - spacing: 12, - runSpacing: 12, - children: List.generate( - 6, - (index) => ZetaMenuItem.vertical( - label: Text('Menu Item'), - icon: Icon(ZetaIcons.star_round), - onTap: () {}, - ), - ), - ), - ); - }, - ); - }, - ), - ZetaMenuItem.horizontal( - label: Text('Horizontal'), - onTap: () { - showModalBottomSheet( - context: context, - builder: (BuildContext context) { - return ZetaBottomSheet( - title: 'Bottom Sheet', - titleAlignment: Alignment.centerLeft, - body: Wrap( - spacing: 12, - runSpacing: 12, - children: List.generate( - 6, - (index) => ZetaMenuItem.horizontal(label: Text('Menu Item'), onTap: () {}), - ), - ), - ); - }, - ); - }, - ), - ZetaMenuItem.horizontal( - label: Text('With center title'), - onTap: () { - showModalBottomSheet( - context: context, - builder: (BuildContext context) { - return ZetaBottomSheet( - title: 'Bottom Sheet', - horizontalAlignment: CrossAxisAlignment.center, - body: Wrap( - spacing: 12, - runSpacing: 12, - children: List.generate( - 6, - (index) => ZetaMenuItem.horizontal(label: Text('Menu Item'), onTap: () {}), - ), - ), - ); - }, - ); - }, - ), - ], - ), - ), - ); - }, - ); - } -} diff --git a/example/lib/pages/components/bottom_sheet_example.dart b/example/lib/pages/components/bottom_sheet_example.dart new file mode 100644 index 00000000..1cc6fa0f --- /dev/null +++ b/example/lib/pages/components/bottom_sheet_example.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class BottomSheetExample extends StatefulWidget { + static const String name = 'BottomSheet'; + + const BottomSheetExample({super.key}); + + @override + State createState() => _BottomSheetExampleState(); +} + +class _BottomSheetExampleState extends State { + bool centerTitle = true; + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: BottomSheetExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(ZetaSpacing.s), + child: Column( + children: [ + ZetaMenuItem.horizontal( + label: Text('Grid'), + onTap: () { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return ZetaBottomSheet( + title: 'Bottom Sheet', + centerTitle: centerTitle, + body: Wrap( + spacing: 12, + runSpacing: 12, + children: List.generate( + 6, + (index) => ZetaMenuItem.vertical( + label: Text('Menu Item'), + icon: Icon(ZetaIcons.star_round), + onTap: () {}, + ), + ), + ), + ); + }, + ); + }, + ), + ZetaMenuItem.horizontal( + label: Text('Horizontal'), + onTap: () { + showZetaBottomSheet( + context: context, + title: 'Bottom Sheet', + centerTitle: centerTitle, + body: Wrap( + spacing: 12, + runSpacing: 12, + children: List.generate( + 6, + (index) => ZetaMenuItem.horizontal( + label: Text('Menu Item'), + onTap: () {}, + leading: Icon(ZetaIcons.star_round), + ), + ), + ), + ); + }, + ), + ZetaCheckbox( + label: 'Center title', + value: centerTitle, + onChanged: (value) => setState(() => centerTitle = !centerTitle), + ), + ], + ), + ), + ); + } +} diff --git a/example/lib/pages/components/button_example.dart b/example/lib/pages/components/button_example.dart index 7723d4ac..c99d80e6 100644 --- a/example/lib/pages/components/button_example.dart +++ b/example/lib/pages/components/button_example.dart @@ -36,100 +36,52 @@ class _ButtonExampleState extends State { fabs = [ ZetaFAB( scrollController: _scrollController, - buttonLabel: 'Small Circle Primary', - buttonSize: ZetaFabSize.small, - buttonShape: ZetaFabShape.circle, - buttonType: ZetaFabType.primary, + label: 'Small Circle Primary', + size: ZetaFabSize.small, + shape: ZetaWidgetBorder.full, + type: ZetaFabType.primary, onPressed: () => setFab(0), ), ZetaFAB( scrollController: _scrollController, - buttonLabel: 'Small Rounded Primary', - buttonSize: ZetaFabSize.small, - buttonShape: ZetaFabShape.rounded, - buttonType: ZetaFabType.primary, + label: 'Small Rounded Primary', + size: ZetaFabSize.small, + shape: ZetaWidgetBorder.rounded, + type: ZetaFabType.secondary, onPressed: () => setFab(1), ), ZetaFAB( scrollController: _scrollController, - buttonLabel: 'Small Sharp Primary', - buttonSize: ZetaFabSize.small, - buttonShape: ZetaFabShape.sharp, - buttonType: ZetaFabType.primary, + label: 'Small Sharp Primary', + size: ZetaFabSize.small, + shape: ZetaWidgetBorder.sharp, + type: ZetaFabType.inverse, onPressed: () => setFab(2), ), ZetaFAB( scrollController: _scrollController, - buttonLabel: 'Small Circle Secondary', - buttonSize: ZetaFabSize.small, - buttonShape: ZetaFabShape.circle, - buttonType: ZetaFabType.primarySecond, + label: 'Large Circle Primary', + size: ZetaFabSize.large, + shape: ZetaWidgetBorder.full, + type: ZetaFabType.secondary, onPressed: () => setFab(3), ), ZetaFAB( scrollController: _scrollController, - buttonLabel: 'Small Circle Secondary', - buttonSize: ZetaFabSize.small, - buttonShape: ZetaFabShape.rounded, - buttonType: ZetaFabType.primarySecond, + label: 'Large Rounded Secondary', + size: ZetaFabSize.large, + shape: ZetaWidgetBorder.rounded, + type: ZetaFabType.inverse, onPressed: () => setFab(4), ), ZetaFAB( scrollController: _scrollController, - buttonLabel: 'Small Sharp Secondary', - buttonSize: ZetaFabSize.small, - buttonShape: ZetaFabShape.sharp, - buttonType: ZetaFabType.primarySecond, + label: 'Large Sharp Secondary', + size: ZetaFabSize.large, + shape: ZetaWidgetBorder.sharp, + type: ZetaFabType.primary, onPressed: () => setFab(5), ), - ZetaFAB( - scrollController: _scrollController, - buttonLabel: 'Large Circle Primary', - buttonSize: ZetaFabSize.large, - buttonShape: ZetaFabShape.circle, - buttonType: ZetaFabType.primary, - onPressed: () => setFab(6), - ), - ZetaFAB( - scrollController: _scrollController, - buttonLabel: 'Large Rounded Primary', - buttonSize: ZetaFabSize.large, - buttonShape: ZetaFabShape.rounded, - buttonType: ZetaFabType.primary, - onPressed: () => setFab(7), - ), - ZetaFAB( - scrollController: _scrollController, - buttonLabel: 'Large Sharp Primary', - buttonSize: ZetaFabSize.large, - buttonShape: ZetaFabShape.sharp, - buttonType: ZetaFabType.primary, - onPressed: () => setFab(8), - ), - ZetaFAB( - scrollController: _scrollController, - buttonLabel: 'Large Circle Primary', - buttonSize: ZetaFabSize.large, - buttonShape: ZetaFabShape.circle, - buttonType: ZetaFabType.primarySecond, - onPressed: () => setFab(9), - ), - ZetaFAB( - scrollController: _scrollController, - buttonLabel: 'Large Rounded Secondary', - buttonSize: ZetaFabSize.large, - buttonShape: ZetaFabShape.rounded, - buttonType: ZetaFabType.primarySecond, - onPressed: () => setFab(10), - ), - ZetaFAB( - scrollController: _scrollController, - buttonLabel: 'Large Sharp Secondary', - buttonSize: ZetaFabSize.large, - buttonShape: ZetaFabShape.sharp, - buttonType: ZetaFabType.primarySecond, - onPressed: () => setFab(11), - ), ]; } @@ -145,11 +97,11 @@ class _ButtonExampleState extends State { child: Column( children: [ Text('Rounded Buttons', style: ZetaTextStyles.displayMedium), - Column(children: buttons(BorderType.rounded)), + Column(children: buttons(ZetaWidgetBorder.rounded)), Text('Sharp Buttons', style: ZetaTextStyles.displayMedium), - Column(children: buttons(BorderType.sharp)), + Column(children: buttons(ZetaWidgetBorder.sharp)), Text('Full Buttons', style: ZetaTextStyles.displayMedium), - Column(children: buttons(BorderType.full)), + Column(children: buttons(ZetaWidgetBorder.full)), Text('Floating Action Buttons', style: ZetaTextStyles.displayMedium), Text('Tap buttons to change current FAB: ', style: ZetaTextStyles.bodyMedium), Wrap(children: fabs.divide(SizedBox.square(dimension: 10)).toList()), @@ -163,7 +115,7 @@ class _ButtonExampleState extends State { ); } - List buttons(BorderType borderType) { + List buttons(ZetaWidgetBorder borderType) { return List.generate( ZetaWidgetSize.values.length + 1, (index) => SingleChildScrollView( diff --git a/example/lib/pages/components/checkbox_example.dart b/example/lib/pages/components/checkbox_example.dart index d274ca75..be48113d 100644 --- a/example/lib/pages/components/checkbox_example.dart +++ b/example/lib/pages/components/checkbox_example.dart @@ -14,6 +14,7 @@ class CheckBoxExample extends StatefulWidget { class _CheckBoxExampleState extends State { bool? isChecked = true; bool isEnabled = true; + bool useIndeterminate = false; @override Widget build(BuildContext context) { @@ -28,11 +29,18 @@ class _CheckBoxExampleState extends State { mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ZetaCheckbox( - value: isChecked, isEnabled: isEnabled, onChanged: (value) => setState(() => isChecked = value)), - ElevatedButton( - child: Text(isEnabled ? 'Disable' : 'Enable'), + value: isChecked, + onChanged: isEnabled ? (value) => setState(() => isChecked = value) : null, + useIndeterminate: useIndeterminate, + ), + ZetaButton( + label: isEnabled ? 'Disable' : 'Enable', onPressed: () => setState(() => isEnabled = !isEnabled), - ) + ), + ZetaButton( + label: !useIndeterminate ? 'Use Indeterminate' : 'Don\'t use indeterminate', + onPressed: () => setState(() => useIndeterminate = !useIndeterminate), + ), ], ), Row(children: [Text('Sharp Checkbox Enabled')]), @@ -56,21 +64,21 @@ Row getCheckBoxRow({required bool isEnabled, bool isSharp = true}) { mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ZetaCheckbox( - value: true, - isEnabled: isEnabled, - label: 'Label', - borderType: isSharp ? BorderType.sharp : BorderType.rounded, - onChanged: (value) => {}), + value: true, + label: 'Label', + rounded: !isSharp, + onChanged: isEnabled ? (value) => {} : null, + ), ZetaCheckbox( - value: false, - isEnabled: isEnabled, - label: 'Label', - borderType: isSharp ? BorderType.sharp : BorderType.rounded, - onChanged: (value) => {}), + value: false, + label: 'Label', + rounded: !isSharp, + onChanged: isEnabled ? (value) => {} : null, + ), ZetaCheckbox( - value: null, - borderType: isSharp ? BorderType.sharp : BorderType.rounded, - isEnabled: isEnabled, - onChanged: (value) => {}), + value: null, + rounded: !isSharp, + onChanged: isEnabled ? (value) => {} : null, + ) ]); } diff --git a/example/lib/pages/components/chip_example.dart b/example/lib/pages/components/chip_example.dart index e859a9ec..cbbc09f2 100644 --- a/example/lib/pages/components/chip_example.dart +++ b/example/lib/pages/components/chip_example.dart @@ -9,190 +9,107 @@ class ChipExample extends StatelessWidget { @override Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - return ExampleScaffold( - name: ChipExample.name, - child: SingleChildScrollView( - padding: EdgeInsets.all(ZetaSpacing.s), - child: Column( - children: [ - ...inputChipExample, - const SizedBox(height: 30), - ...assistChipExample, - const SizedBox(height: 30), - ...filterChipExample, - const SizedBox(height: 30), - ...statusChipExample, - ], - ), + final List inputChipExample = [ + Text( + 'Input Chip', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + Text( + 'Rounded', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text('Label Only', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaInputChip(label: 'Label'), + const SizedBox(height: 30), + Text('Label + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaInputChip( + label: 'Label', + ), + const SizedBox(height: 30), + Text('Label + Avatar', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaInputChip( + label: 'Label', + leading: const Icon(ZetaIcons.user_round), + ), + const SizedBox(height: 30), + Text('Label, Avatar + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaInputChip( + label: 'Label', + leading: const Icon(ZetaIcons.user_round), + trailing: Icon(ZetaIcons.close_round), + ), + ], ), - ); - }, - ); - } - - static List inputChipExample = [ - Text( - 'Input Chip', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - children: [ - Text( - 'Rounded', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 30), - Text('Label Only', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.input(label: 'Label'), - const SizedBox(height: 30), - Text('Label + Icon', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.input( - label: 'Label', - onDelete: () {}, - ), - const SizedBox(height: 30), - Text('Label + Avatar', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.input( - label: 'Label', - leading: const Icon(ZetaIcons.avatar), - ), - const SizedBox(height: 30), - Text('Label, Avatar + Icon', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.input( - label: 'Label', - leading: const Icon(ZetaIcons.avatar), - onDelete: () {}, - ), - ], - ), - Column( - children: [ - Text( - 'Sharp', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 30), - Text('Label Only', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.input( - label: 'Label', - rounded: false, - ), - const SizedBox(height: 30), - Text('Label + Icon', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.input( - label: 'Label', - rounded: false, - onDelete: () {}, - ), - const SizedBox(height: 30), - Text('Label + Avatar', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.input( - label: 'Label', - rounded: false, - leading: const Icon(ZetaIcons.avatar), - ), - const SizedBox(height: 30), - Text('Label, Avatar + Icon', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.input( - label: 'Label', - rounded: false, - leading: const Icon(ZetaIcons.avatar), - onDelete: () {}, - ), - ], - ), - ], - ), - ]; - - static List assistChipExample = [ - Text( - 'Assist Chip', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - children: [ - Text( - 'Rounded', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 30), - Text('Label Only', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.assist(label: 'Label'), - const SizedBox(height: 30), - Text('Label + Icon', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.assist( - label: 'Label', - showIcon: true, - ), - ], - ), - Column( - children: [ - Text( - 'Sharp', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 30), - Text('Label Only', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.assist( - label: 'Label', - rounded: false, - ), - const SizedBox(height: 30), - Text('Label + Icon', textAlign: TextAlign.center), - const SizedBox(height: 10), - ZetaChip.assist( - label: 'Label', - rounded: false, - showIcon: true, - ), - ], - ), - ], - ), - ]; + Column( + children: [ + Text( + 'Sharp', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text('Label Only', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaInputChip( + label: 'Label', + rounded: false, + ), + const SizedBox(height: 30), + Text('Label + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaInputChip( + label: 'Label', + rounded: false, + ), + const SizedBox(height: 30), + Text('Label + Avatar', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaInputChip( + label: 'Label', + rounded: false, + leading: const Icon(ZetaIcons.user_round), + ), + const SizedBox(height: 30), + Text('Label, Avatar + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaInputChip( + label: 'Label', + rounded: false, + leading: const Icon(ZetaIcons.user_round), + trailing: Icon(ZetaIcons.close_sharp), + ), + ], + ), + ], + ), + ]; - static List filterChipExample = [ - Text( - 'Filter Chip', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - Row( - children: [ - Expanded( - child: Column( + final List filterChipExample = [ + Text( + 'Filter Chip', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( children: [ Text( 'Rounded', @@ -208,9 +125,7 @@ class ChipExample extends StatelessWidget { ), ], ), - ), - Expanded( - child: Column( + Column( children: [ Text( 'Sharp', @@ -230,30 +145,84 @@ class ChipExample extends StatelessWidget { ), ], ), - ), - ], - ), - ]; + ], + ), + ]; + + final List assistChipExample = [ + Text( + 'Assist Chip', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + Text( + 'Rounded', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text('Label Only', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaAssistChip(label: 'Label'), + const SizedBox(height: 30), + Text('Label + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaAssistChip( + label: 'Label', + leading: Icon(ZetaIcons.star_round), + ), + ], + ), + Column( + children: [ + Text( + 'Sharp', + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Text('Label Only', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaAssistChip( + label: 'Label', + rounded: false, + ), + const SizedBox(height: 30), + Text('Label + Icon', textAlign: TextAlign.center), + const SizedBox(height: 10), + ZetaAssistChip( + label: 'Label', + rounded: false, + leading: Icon(ZetaIcons.star_round), + ), + ], + ), + ], + ), + ]; - static List statusChipExample = [ - Text( - 'Status Chip', - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - ZetaChip.status('Input Custom'), - const SizedBox(height: 10), - ZetaChip.status('New'), - const SizedBox(height: 10), - ZetaChip.status('In Progress'), - const SizedBox(height: 10), - ZetaChip.status('Completed'), - const SizedBox(height: 10), - ZetaChip.status('Done'), - const SizedBox(height: 10), - ZetaChip.status('Drafting'), - const SizedBox(height: 10), - ZetaChip.status('--'), - ]; + return ExampleScaffold( + name: ChipExample.name, + child: SingleChildScrollView( + padding: EdgeInsets.all(ZetaSpacing.s), + child: Column( + children: [ + ...inputChipExample, + const SizedBox(height: 30), + ...assistChipExample, + const SizedBox(height: 30), + ...filterChipExample, + const SizedBox(height: 30), + ], + ), + ), + ); + } } diff --git a/example/lib/pages/components/password_input_example.dart b/example/lib/pages/components/password_input_example.dart index 7d8db570..d7a46e20 100644 --- a/example/lib/pages/components/password_input_example.dart +++ b/example/lib/pages/components/password_input_example.dart @@ -37,7 +37,7 @@ class _PasswordInputExampleState extends State { Padding(padding: EdgeInsets.only(top: 20)), ZetaPasswordInput( size: ZetaWidgetSize.medium, - borderType: BorderType.sharp, + rounded: false, footerText: 'Error state is triggered if the password contains digits', footerIcon: ZetaIcons.info_round, hintText: 'Password', @@ -65,21 +65,19 @@ class _PasswordInputExampleState extends State { } } -List passwordInputExampleRow( - ZetaWidgetSize size, { - BorderType borderType = BorderType.rounded, -}) { +List passwordInputExampleRow(ZetaWidgetSize size, {bool rounded = true}) { return [ - ZetaPasswordInput(size: size, hintText: 'Password', borderType: borderType), + ZetaPasswordInput(size: size, hintText: 'Password', rounded: rounded), SizedBox(height: 20), - ZetaPasswordInput(borderType: borderType, size: size, hintText: 'Password', enabled: false), + ZetaPasswordInput(rounded: rounded, size: size, hintText: 'Password', enabled: false), SizedBox(height: 20), ZetaPasswordInput( - size: size, - label: 'Label', - hintText: 'Password', - footerText: 'Default hint text', - borderType: borderType, - footerIcon: ZetaIcons.info_round), + size: size, + label: 'Label', + hintText: 'Password', + footerText: 'Default hint text', + rounded: rounded, + footerIcon: ZetaIcons.info_round, + ), ]; } diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index 2b66f435..151506c3 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -1,27 +1,20 @@ PODS: - FlutterMacOS (1.0.0) - - FMDB (2.7.5): - - FMDB/standard (= 2.7.5) - - FMDB/standard (2.7.5) - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - - sqflite (0.0.2): + - sqflite (0.0.3): + - Flutter - FlutterMacOS - - FMDB (>= 2.7.5) DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) - -SPEC REPOS: - trunk: - - FMDB + - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) EXTERNAL SOURCES: FlutterMacOS: @@ -31,14 +24,13 @@ EXTERNAL SOURCES: shared_preferences_foundation: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin sqflite: - :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos + :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 - sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index d644e73f..253d9342 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -159,7 +159,6 @@ 775BFA427E635DE4CCD15022 /* Pods-Runner.release.xcconfig */, 89C2799490DE736CE6C6B909 /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; diff --git a/example/pubspec.lock b/example/pubspec.lock index aafb7441..cfd72c73 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -26,29 +26,29 @@ packages: source: hosted version: "2.1.1" cached_network_image: - dependency: transitive + dependency: "direct main" description: name: cached_network_image - sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f + sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.3.1" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613" + sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "4.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257" + sha256: "42a835caa27c220d1294311ac409a43361088625a4f23c820b006dd9bffb3316" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" characters: dependency: transitive description: @@ -113,6 +113,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -409,18 +417,18 @@ packages: dependency: transitive description: name: sqflite - sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.2" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 + sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" url: "https://pub.dev" source: hosted - version: "2.5.0+2" + version: "2.5.3" stack_trace: dependency: transitive description: @@ -481,10 +489,10 @@ packages: dependency: transitive description: name: uuid - sha256: "22c94e5ad1e75f9934b766b53c742572ee2677c56bc871d850a57dad0f82127f" + sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 url: "https://pub.dev" source: hosted - version: "4.2.2" + version: "4.3.3" vector_math: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 74d5c998..6b891784 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -7,6 +7,7 @@ environment: sdk: ">=3.0.1 <4.0.0" dependencies: + cached_network_image: ^3.3.1 flutter: sdk: flutter go_router: ^11.1.2 diff --git a/example/test/checkbox_test.dart b/example/test/checkbox_test.dart index 882cfa3a..78ba7381 100644 --- a/example/test/checkbox_test.dart +++ b/example/test/checkbox_test.dart @@ -1,41 +1,43 @@ +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import 'package:flutter/material.dart'; + +import 'test_components.dart'; void main() { group('ZetaCheckbox Tests', () { testWidgets('Initializes with correct parameters', (WidgetTester tester) async { await tester.pumpWidget( - TestWidgetCB( - widget: ZetaCheckbox( - value: true, - onChanged: (value) {}, - borderType: BorderType.rounded, - label: 'Test Checkbox', - checkboxSize: Size(30, 30), - )), + TestWidget( + widget: ZetaCheckbox( + value: true, + onChanged: (value) {}, + label: 'Test Checkbox', + ), + ), ); final checkboxFinder = find.byType(ZetaCheckbox); final ZetaCheckbox checkbox = tester.firstWidget(checkboxFinder); expect(checkbox.value, true); - expect(checkbox.borderType, BorderType.rounded); + expect(checkbox.rounded, true); expect(checkbox.label, 'Test Checkbox'); - expect(checkbox.checkboxSize, Size(30, 30)); }); testWidgets('ZetaCheckbox changes state on tap', (WidgetTester tester) async { bool? checkboxValue = true; await tester.pumpWidget( - TestWidgetCB( - widget: ZetaCheckbox( - value: checkboxValue, - onChanged: (value) { - checkboxValue = value; - }, - )), + TestWidget( + removeBody: true, + widget: ZetaCheckbox( + value: checkboxValue, + onChanged: (value) { + checkboxValue = value; + }, + ), + ), ); await tester.tap(find.byType(ZetaCheckbox)); diff --git a/example/test/fab_test.dart b/example/test/fab_test.dart index d9a9311a..63bebbc0 100644 --- a/example/test/fab_test.dart +++ b/example/test/fab_test.dart @@ -11,7 +11,7 @@ void main() { await tester.pumpWidget(TestWidget( widget: ZetaFAB( scrollController: scrollController, - buttonLabel: 'Label', + label: 'Label', ))); expect(find.byType(ZetaFAB), findsOneWidget); @@ -24,7 +24,7 @@ void main() { await tester.pumpWidget(TestWidget( widget: ZetaFAB( scrollController: scrollController, - buttonLabel: 'Label', + label: 'Label', onPressed: () => isPressed = true, ))); @@ -39,7 +39,7 @@ void main() { await tester.pumpWidget(TestWidget( widget: ZetaFAB( scrollController: scrollController, - buttonLabel: 'Label', + label: 'Label', ))); expect(find.byIcon(ZetaIcons.add_round), findsOneWidget); }); diff --git a/example/test/in_page_banner_test.dart b/example/test/in_page_banner_test.dart index c05081a8..bf28f160 100644 --- a/example/test/in_page_banner_test.dart +++ b/example/test/in_page_banner_test.dart @@ -34,7 +34,7 @@ void main() { TestWidget( widget: ZetaInPageBanner( content: Text('Test'), - showIconClose: true, + onClose: () {}, )), ); expect(find.byIcon(ZetaIcons.close_round), findsOneWidget); @@ -43,7 +43,6 @@ void main() { TestWidget( widget: ZetaInPageBanner( content: Text('Test'), - showIconClose: false, )), ); expect(find.byIcon(ZetaIcons.close_sharp), findsNothing); diff --git a/example/test/test_components.dart b/example/test/test_components.dart index 60197103..38c78b57 100644 --- a/example/test/test_components.dart +++ b/example/test/test_components.dart @@ -5,8 +5,15 @@ class TestWidget extends StatelessWidget { final Size? screenSize; final Widget widget; final ThemeMode? themeMode; + final bool removeBody; - const TestWidget({required this.widget, this.screenSize, super.key, this.themeMode}); + const TestWidget({ + required this.widget, + this.screenSize, + super.key, + this.themeMode, + this.removeBody = false, + }); @override Widget build(BuildContext context) { @@ -30,14 +37,16 @@ class TestWidget extends StatelessWidget { textTheme: zetaTextTheme, ), home: Scaffold( - body: SizedBox( - width: size.width, - height: size.height, - child: MediaQuery( - data: MediaQueryData(size: Size(size.width, size.height)), - child: SingleChildScrollView(child: widget), - ), - ), + 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/components/accordion_widgetbook.dart b/example/widgetbook/components/accordion_widgetbook.dart index e187d8fa..2cd130c5 100644 --- a/example/widgetbook/components/accordion_widgetbook.dart +++ b/example/widgetbook/components/accordion_widgetbook.dart @@ -16,23 +16,20 @@ WidgetbookComponent accordionWidgetBook() { widget: Padding( padding: const EdgeInsets.all(20), child: ZetaAccordion( - children: [ - ZetaAccordionSection( - title: Text(context.knobs.string(label: 'Accordion Title', initialValue: 'Title')), - disabled: context.knobs.boolean(label: 'Disabled', initialValue: false), - contained: context.knobs.boolean(label: 'Contained', initialValue: false), - isOpen: context.knobs.boolean(label: 'Open', initialValue: false), - rounded: context.knobs.boolean(label: 'Rounded', initialValue: false), - body: Column( - children: [ - ListTile(title: Text('Item One')), - ListTile(title: Text('Item two')), - ListTile(title: Text('Item three')), - ListTile(title: Text('Item four')), - ], - ), - ), - ], + 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 faddc32b..ff73ed42 100644 --- a/example/widgetbook/components/avatar_widgetbook.dart +++ b/example/widgetbook/components/avatar_widgetbook.dart @@ -10,7 +10,34 @@ WidgetbookComponent avatarWidgetBook() { name: 'Avatar', useCases: [ WidgetbookUseCase( - name: 'Avatar', + name: 'Image Avatar', + builder: (context) { + final Widget image = Image.network('https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', fit: BoxFit.cover); + + return TestWidget( + themeMode: ThemeMode.dark, + widget: Column( + children: [ + Padding( + padding: const EdgeInsets.all(20), + child: ZetaAvatar.image( + image: context.knobs.boolean(label: 'Image') ? image : null, + size: context.knobs.list(label: 'Size', options: ZetaAvatarSize.values), + lowerBadge: + context.knobs.boolean(label: 'Status Badge', initialValue: false) ? ZetaIndicator.icon() : null, + borderColor: context.knobs.colorOrNull(label: 'Outline', initialValue: null), + upperBadge: context.knobs.boolean(label: 'Notification Badge', initialValue: false) + ? ZetaIndicator.notification() + : null, + ), + ), + ], + ), + ); + }, + ), + WidgetbookUseCase( + name: 'Initials Avatar', builder: (context) { return TestWidget( themeMode: ThemeMode.dark, @@ -18,25 +45,17 @@ WidgetbookComponent avatarWidgetBook() { children: [ Padding( padding: const EdgeInsets.all(20), - child: ZetaAvatar( - type: context.knobs.list(label: 'Avatar type', options: ZetaAvatarType.values), - imageUrl: context.knobs.string( - label: 'Image URL', - initialValue: 'https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', - ), - initials: context.knobs.string(label: 'Initials', initialValue: 'AZ'), - showStatus: context.knobs.boolean(label: 'Show Status'), + child: ZetaAvatar.initials( + backgroundColor: context.knobs.colorOrNull(label: 'Background color', initialValue: null), + initials: context.knobs.stringOrNull(label: 'Initials', initialValue: 'AB'), size: context.knobs.list(label: 'Size', options: ZetaAvatarSize.values), - badge: () { - final x = context.knobs.intOrNull.slider(label: 'Notifications', initialValue: null, max: 10); - if (x == null) return null; - return ZetaIndicator.notification(value: x); - }(), - specialStatus: - context.knobs.boolean(label: 'Status Icon', initialValue: false) ? ZetaIndicator.icon() : null, - backgroundColor: context.knobs.colorOrNull(label: 'Background color'), - statusPrimaryColor: context.knobs.colorOrNull(label: 'Status primary color'), - statusSecondaryColor: context.knobs.colorOrNull(label: 'Status secondary color'), + lowerBadge: context.knobs.boolean(label: 'Status badge', initialValue: false) + ? ZetaIndicator.notification() + : null, + borderColor: context.knobs.colorOrNull(label: 'Outline', initialValue: null), + upperBadge: context.knobs.boolean(label: 'Notification badge', initialValue: false) + ? ZetaIndicator.icon() + : null, ), ), ], diff --git a/example/widgetbook/components/badges_widgetbook.dart b/example/widgetbook/components/badges_widgetbook.dart index 6e3677c6..6147d1bb 100644 --- a/example/widgetbook/components/badges_widgetbook.dart +++ b/example/widgetbook/components/badges_widgetbook.dart @@ -110,7 +110,7 @@ WidgetbookComponent badgeWidgetBook() { }, ), inverse: context.knobs.boolean(label: 'Inverse Border'), - size: context.knobs.list(label: 'Size', options: ZetaIndicatorSize.values), + size: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), value: context.knobs.int.slider(label: 'Value'), ), ), diff --git a/example/widgetbook/components/banner_widgetbook.dart b/example/widgetbook/components/banner_widgetbook.dart index fe571767..b6dceb62 100644 --- a/example/widgetbook/components/banner_widgetbook.dart +++ b/example/widgetbook/components/banner_widgetbook.dart @@ -62,8 +62,8 @@ WidgetbookComponent BannerWidgetBook() { 'Lorem ipsum dolor sit amet, conse ctetur cididunt ut labore et do lore magna aliqua.', ), ), - severity: context.knobs.list(label: 'Severity', options: ZetaWidgetStatus.values), - showIconClose: context.knobs.boolean(label: 'Show Close icon'), + status: context.knobs.list(label: 'Severity', options: ZetaWidgetStatus.values), + onClose: context.knobs.boolean(label: 'Show Close icon') ? () {} : null, title: context.knobs.string(label: 'Title', initialValue: 'Title'), rounded: context.knobs.boolean(label: 'Rounded'), actions: () { diff --git a/example/widgetbook/components/bottom_sheet_widgetbook.dart b/example/widgetbook/components/bottom_sheet_widgetbook.dart index 00d42267..2bb95e37 100644 --- a/example/widgetbook/components/bottom_sheet_widgetbook.dart +++ b/example/widgetbook/components/bottom_sheet_widgetbook.dart @@ -24,6 +24,7 @@ WidgetbookComponent bottomSheetWidgetBook() { builder: (context) { final sheet = _bottomSheet(context); return TestWidget( + themeMode: ThemeMode.dark, widget: Padding( padding: const EdgeInsets.all(20), child: ElevatedButton( @@ -42,7 +43,7 @@ WidgetbookComponent bottomSheetWidgetBook() { ZetaBottomSheet _bottomSheet(BuildContext context) { return ZetaBottomSheet( - titleAlignment: context.knobs.boolean(label: 'Center align header') ? Alignment.center : Alignment.centerLeft, + centerTitle: context.knobs.boolean(label: 'Center title', initialValue: true), title: context.knobs.string(label: 'Title', initialValue: 'Title'), body: Wrap( spacing: 12, @@ -51,11 +52,10 @@ ZetaBottomSheet _bottomSheet(BuildContext context) { 6, (index) => ZetaMenuItem( type: context.knobs.boolean(label: 'Grid') ? ZetaMenuItemType.vertical : ZetaMenuItemType.horizontal, - leadingIcon: context.knobs.boolean(label: 'Leading Icon') ? Icon(ZetaIcons.star_round) : null, - trailingIcon: context.knobs.boolean(label: 'Trailing Icon') ? Icon(ZetaIcons.chevron_right_round) : null, + leading: context.knobs.boolean(label: 'Leading Icon') ? Icon(ZetaIcons.star_round) : null, + trailing: context.knobs.boolean(label: 'Trailing Icon') ? Icon(ZetaIcons.chevron_right_round) : null, label: Text('Menu Item'), - onTap: () {}, - disabled: context.knobs.boolean(label: 'Disabled'), + onTap: context.knobs.boolean(label: 'Disabled') ? null : () {}, ), ), ), diff --git a/example/widgetbook/components/button_widgetbook.dart b/example/widgetbook/components/button_widgetbook.dart index 91b2fc4b..2f3f3655 100644 --- a/example/widgetbook/components/button_widgetbook.dart +++ b/example/widgetbook/components/button_widgetbook.dart @@ -18,7 +18,7 @@ WidgetbookComponent buttonWidgetBook() { child: ZetaButton( label: context.knobs.string(label: 'Text', initialValue: 'Button'), onPressed: context.knobs.boolean(label: 'Disabled') ? null : () {}, - borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + 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), ), @@ -73,9 +73,9 @@ class _FabWidgetState extends State { ), floatingActionButton: ZetaFAB( scrollController: _scrollController, - buttonLabel: widget.c.knobs.string(label: 'Label', initialValue: 'Floating Action Button'), + label: widget.c.knobs.string(label: 'Label', initialValue: 'Floating Action Button'), onPressed: widget.c.knobs.boolean(label: 'Disabled') ? null : () {}, - buttonIcon: widget.c.knobs.list( + icon: widget.c.knobs.list( label: 'Icon', options: [ ZetaIcons.star_half_round, @@ -91,11 +91,9 @@ class _FabWidgetState extends State { return ''; }, ), - buttonShape: widget.c.knobs.list(label: 'Shape', options: ZetaFabShape.values), - buttonSize: widget.c.knobs.list(label: 'Shape', options: ZetaFabSize.values), - buttonType: widget.c.knobs.list(label: 'Shape', options: ZetaFabType.values), - customAnimationDuration: - widget.c.knobs.duration(label: 'Animation Duration', initialValue: Duration(milliseconds: 100)), + shape: widget.c.knobs.list(label: 'Shape', options: ZetaWidgetBorder.values), + size: widget.c.knobs.list(label: 'Shape', options: ZetaFabSize.values), + type: widget.c.knobs.list(label: 'Shape', options: ZetaFabType.values), ), ), ); diff --git a/example/widgetbook/components/checkbox_widgetbook.dart b/example/widgetbook/components/checkbox_widgetbook.dart index 4df00343..5883b6d0 100644 --- a/example/widgetbook/components/checkbox_widgetbook.dart +++ b/example/widgetbook/components/checkbox_widgetbook.dart @@ -18,9 +18,8 @@ WidgetbookComponent checkboxWidgetBook() { padding: EdgeInsets.only(top: 10), child: ZetaCheckbox( value: context.knobs.booleanOrNull(label: 'Checked'), - onChanged: (_) {}, - borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, - isEnabled: context.knobs.boolean(label: 'Enabled', initialValue: true), + 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/components/chip_widgetbook.dart b/example/widgetbook/components/chip_widgetbook.dart index 3ec6a6d7..072617dc 100644 --- a/example/widgetbook/components/chip_widgetbook.dart +++ b/example/widgetbook/components/chip_widgetbook.dart @@ -11,23 +11,38 @@ WidgetbookComponent chipWidgetBook() { useCases: [ WidgetbookUseCase( name: 'Input Chip', - builder: (context) => TestWidget( - widget: Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - ZetaChip.input( - label: context.knobs.string(label: 'Label', initialValue: 'Label'), - leading: context.knobs.boolean(label: 'Avatar') - ? ZetaAvatar.initials(initials: 'AZ', size: ZetaAvatarSize.xs) - : null, - rounded: context.knobs.boolean(label: 'Rounded'), - onDelete: context.knobs.boolean(label: 'Delete') ? () {} : null, - ), - ], + builder: (context) { + final trailing = context.knobs.listOrNull( + label: 'Icon', + options: [ + ZetaIcons.star_half_round, + ZetaIcons.add_alert_round, + ZetaIcons.add_box_round, + ZetaIcons.barcode_round, + ], + initialOption: null, + labelBuilder: (value) { + if (value == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; + if (value == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; + if (value == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; + if (value == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; + return ''; + }, + ); + return TestWidget( + 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, ), - ), - ), + ); + }, ), WidgetbookUseCase( name: 'Filter Chip', @@ -40,7 +55,6 @@ WidgetbookComponent chipWidgetBook() { label: context.knobs.string(label: 'Label', initialValue: 'Label'), rounded: context.knobs.boolean(label: 'Rounded'), selected: context.knobs.boolean(label: 'Selected'), - onChange: context.knobs.boolean(label: 'Enabled') ? ({bool value = false}) {} : null, ) ], ), @@ -54,41 +68,16 @@ WidgetbookComponent chipWidgetBook() { padding: const EdgeInsets.all(20), child: Column( children: [ - ZetaChip.assist( + ZetaAssistChip( label: context.knobs.string(label: 'Label', initialValue: 'Label'), rounded: context.knobs.boolean(label: 'Rounded'), - showIcon: context.knobs.boolean(label: 'Show Icon'), - icon: context.knobs.list( - label: 'Icon', - options: [ - Icon(ZetaIcons.star_half_round), - Icon(ZetaIcons.add_alert_round), - Icon(ZetaIcons.add_box_round), - Icon(ZetaIcons.barcode_round), - ], - labelBuilder: (value) { - if ((value as Icon).icon == ZetaIcons.star_half_round) return 'ZetaIcons.star_half_round'; - if ((value).icon == ZetaIcons.add_alert_round) return 'ZetaIcons.add_alert_round'; - if ((value).icon == ZetaIcons.add_box_round) return 'ZetaIcons.add_box_round'; - if ((value).icon == ZetaIcons.barcode_round) return 'ZetaIcons.barcode_round'; - return ''; - }, - ), + leading: context.knobs.boolean(label: 'Icon') ? Icon(ZetaIcons.star_round) : null, ) ], ), ), ), ), - WidgetbookUseCase( - name: 'Status Chip', - builder: (context) => TestWidget( - widget: Padding( - padding: const EdgeInsets.all(20), - child: Column(children: [ZetaChip.status(context.knobs.string(label: 'Label', initialValue: 'Label'))]), - ), - ), - ), ], ); } diff --git a/example/widgetbook/components/password_input_widgetbook.dart b/example/widgetbook/components/password_input_widgetbook.dart index 16b0a036..fdfe3c5b 100644 --- a/example/widgetbook/components/password_input_widgetbook.dart +++ b/example/widgetbook/components/password_input_widgetbook.dart @@ -44,7 +44,7 @@ class _PasswordState extends State<_Password> { ConstrainedBox( constraints: BoxConstraints(maxWidth: 328), child: ZetaPasswordInput( - borderType: context.knobs.boolean(label: 'Rounded') ? BorderType.rounded : BorderType.sharp, + rounded: context.knobs.boolean(label: 'Rounded'), enabled: context.knobs.boolean(label: 'Enabled', initialValue: true), obscureText: context.knobs.boolean(label: 'Obscure text', initialValue: true), size: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), diff --git a/lib/src/assets/icons.dart b/lib/src/assets/icons.dart index f11ecfdf..682fc135 100644 --- a/lib/src/assets/icons.dart +++ b/lib/src/assets/icons.dart @@ -6,7 +6,6 @@ class ZetaIcons { ZetaIcons._(); static const String _familyRound = 'zeta-icons-round'; static const String _familySharp = 'zeta-icons-sharp'; - static const String _familyOther = 'zeta-icons-other'; static const String _package = 'zeta_flutter'; // round @@ -1006,7 +1005,4 @@ class ZetaIcons { static const IconData star_sharp = IconData(0xe1e2, fontFamily: _familySharp, fontPackage: _package); static const IconData toggle_off_sharp = IconData(0xe1e3, fontFamily: _familySharp, fontPackage: _package); static const IconData toggle_on_sharp = IconData(0xe1e4, fontFamily: _familySharp, fontPackage: _package); - - // other icons - static const IconData avatar = IconData(0xe900, fontFamily: _familyOther, fontPackage: _package); } diff --git a/lib/src/components/accordion/accordion.dart b/lib/src/components/accordion/accordion.dart index 928c3c79..6b2966f8 100644 --- a/lib/src/components/accordion/accordion.dart +++ b/lib/src/components/accordion/accordion.dart @@ -8,17 +8,21 @@ import '../../../zeta_flutter.dart'; /// such as labels or thumbnails. Each item can be "expanded" or "collapsed" to reveal /// the content associated with that item. There can be zero expanded items, exactly one, /// or more than one item expanded at a time, depending on the configuration. -class ZetaAccordion extends StatelessWidget { +class ZetaAccordion extends StatefulWidget { /// The constructor of the component [ZetaAccordion]. const ZetaAccordion({ super.key, - required this.children, + required this.title, + this.child, this.rounded = true, this.contained = false, + this.isOpen = false, }); - /// List of [ZetaAccordionSection] to show in [ZetaAccordion]. - final List children; + /// Children displayed when component is opened. + /// + /// If null, component will render as disabled. + final Widget? child; /// {@template zeta-component-rounded} /// Sets rounded or sharp border of the containing box and the icon style. @@ -27,104 +31,32 @@ class ZetaAccordion extends StatelessWidget { /// {@endtemplate} final bool rounded; - /// Determines if the [ZetaAccordionSection]s should be in a box. + /// Determines if the [ZetaAccordion]s should be in a box. /// /// Defaults to `false`. final bool contained; - @override - Widget build(BuildContext context) { - return DecoratedBox( - decoration: BoxDecoration( - borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, - border: Border(top: BorderSide(color: Zeta.of(context).colors.cool.shade40)), - ), - child: ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - itemCount: children.length, - itemBuilder: (context, index) => children[index].copyWith(rounded: rounded, contained: contained), - ), - ); - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('rounded', rounded)) - ..add(DiagnosticsProperty('contained', contained)); - } -} - -// TODO(thelukewalton): Consider changing this to improve developer experience. - -/// The element for the `children` of [ZetaAccordion] -class ZetaAccordionSection extends StatefulWidget { - /// The constructor of the [ZetaAccordionSection] - const ZetaAccordionSection({ - super.key, - required this.title, - required this.body, - this.isOpen = false, - this.disabled = false, - this.rounded = true, - this.contained = false, - }); - - /// The header of the [ZetaAccordionSection]. - final Widget title; + /// Title of Accordion. + final String title; - /// The content of the [ZetaAccordionSection]. - final Widget body; - - /// Sets the initial state of the [ZetaAccordionSection]. - /// Default is `false`. + /// Whether the accordion is open or closed. + /// + /// Defaults to false(closed). final bool isOpen; - - /// Determines if [ZetaAccordionSection] should be disabled. - /// Default is `false`. - final bool disabled; - - /// Sets rounded or sharp border of the containing box and the icon style. - /// Default is `true`. - final bool rounded; - - /// Determines if the [ZetaAccordionSection]s should be in a box. - /// Default is `false` - final bool contained; - @override - State createState() => _ZetaAccordionSectionState(); - - /// Creates another instance of the same [ZetaAccordionSection], - /// but with modified properties. - ZetaAccordionSection copyWith({ - bool rounded = true, - bool contained = false, - }) { - return ZetaAccordionSection( - title: title, - body: body, - isOpen: isOpen, - disabled: disabled, - rounded: rounded, - contained: contained, - ); - } - + State createState() => _ZetaAccordionState(); @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(DiagnosticsProperty('isOpen', isOpen)) - ..add(DiagnosticsProperty('disabled', disabled)) ..add(DiagnosticsProperty('rounded', rounded)) - ..add(DiagnosticsProperty('contained', contained)); + ..add(DiagnosticsProperty('contained', contained)) + ..add(StringProperty('title', title)) + ..add(DiagnosticsProperty('isOpen', isOpen)); } } -class _ZetaAccordionSectionState extends State with TickerProviderStateMixin { +class _ZetaAccordionState extends State with TickerProviderStateMixin { late bool _isOpen; late bool _disabled; late final AnimationController _controller; @@ -146,14 +78,14 @@ class _ZetaAccordionSectionState extends State with Ticker } @override - void didUpdateWidget(ZetaAccordionSection oldWidget) { + void didUpdateWidget(ZetaAccordion oldWidget) { init(); super.didUpdateWidget(oldWidget); } void init() { _isOpen = widget.isOpen; - _disabled = widget.disabled; + _disabled = widget.child == null; } @override @@ -165,65 +97,88 @@ class _ZetaAccordionSectionState extends State with Ticker @override Widget build(BuildContext context) { final zetaColors = Zeta.of(context).colors; - + final borderColor = _disabled ? zetaColors.borderDisabled : zetaColors.borderSubtle; return DecoratedBox( decoration: BoxDecoration( - border: widget.contained - ? Border.all( - color: _disabled ? zetaColors.borderDisabled : zetaColors.borderDefault, - ) - : null, + border: widget.contained ? Border.all(color: borderColor) : Border(top: BorderSide(color: borderColor)), borderRadius: widget.rounded ? ZetaRadius.minimal : ZetaRadius.none, ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - InkWell( - onTap: _disabled - ? null - : () => setState(() { - if (_isOpen) { - _controller.reverse(); - _isOpen = false; - } else { - _isOpen = true; - _controller.forward(); - } - }), - hoverColor: Zeta.of(context).colors.cool.shade20, - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - DefaultTextStyle( - style: ZetaTextStyles.titleMedium.apply( - color: _disabled ? zetaColors.textDisabled : zetaColors.textDefault, + child: Padding( + padding: const EdgeInsets.all(1), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextButton( + style: ButtonStyle( + shape: MaterialStatePropertyAll( + RoundedRectangleBorder(borderRadius: widget.rounded ? ZetaRadius.minimal : ZetaRadius.none), + ), + overlayColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.hovered)) { + return zetaColors.cool.shade20; + } + if (states.contains(MaterialState.pressed)) { + return zetaColors.cool.shade30; + } + + if (states.contains(MaterialState.focused)) { + return Colors.transparent; + } + + return null; + }), + side: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.focused)) { + return BorderSide(color: zetaColors.blue.shade50, width: 2); + } + return null; + }), + ), + onPressed: _disabled + ? null + : () => setState(() { + if (_isOpen) { + _controller.reverse(); + _isOpen = false; + } else { + _isOpen = true; + _controller.forward(); + } + }), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + DefaultTextStyle( + style: ZetaTextStyles.titleMedium.apply( + color: _disabled ? zetaColors.textDisabled : zetaColors.textDefault, + ), + child: Flexible(child: Text(widget.title)), ), - child: Flexible(child: widget.title), - ), - Padding( - padding: const EdgeInsets.only(left: ZetaSpacing.x4), - child: Icon( - _isOpen - ? (widget.rounded ? ZetaIcons.remove_round : ZetaIcons.remove_sharp) - : (widget.rounded ? ZetaIcons.add_round : ZetaIcons.add_sharp), - color: _disabled ? zetaColors.iconDisabled : zetaColors.iconDefault, + Padding( + padding: const EdgeInsets.only(left: ZetaSpacing.x4), + child: Icon( + _isOpen + ? (widget.rounded ? ZetaIcons.remove_round : ZetaIcons.remove_sharp) + : (widget.rounded ? ZetaIcons.add_round : ZetaIcons.add_sharp), + color: _disabled ? zetaColors.iconDisabled : zetaColors.iconDefault, + ), ), - ), - ], + ], + ), ), ), - ), - SizeTransition( - sizeFactor: _animation, - axisAlignment: -1, - child: Padding( - padding: const EdgeInsets.fromLTRB(ZetaSpacing.x4, ZetaSpacing.x0, ZetaSpacing.x4, ZetaSpacing.x4), - child: DefaultTextStyle(style: ZetaTextStyles.titleSmall, child: widget.body), + SizeTransition( + sizeFactor: _animation, + axisAlignment: -1, + child: Padding( + padding: const EdgeInsets.fromLTRB(ZetaSpacing.x4, 0, ZetaSpacing.x4, ZetaSpacing.x4), + child: DefaultTextStyle(style: ZetaTextStyles.titleSmall, child: widget.child ?? const SizedBox()), + ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/src/components/avatars/avatar.dart b/lib/src/components/avatars/avatar.dart index 77055c6b..376c9f28 100644 --- a/lib/src/components/avatars/avatar.dart +++ b/lib/src/components/avatars/avatar.dart @@ -1,19 +1,7 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -// TODO(thelukewalton): Think more about this. - -/// [ZetaAvatar] type -enum ZetaAvatarType { - /// [image] shows a picture or a placeholder - image, - - /// [initials] shows one or two letters - initials, -} - /// [ZetaAvatar] size enum ZetaAvatarSize { /// [xl] 64 pixels @@ -35,372 +23,213 @@ enum ZetaAvatarSize { /// ZetaAvatar component class ZetaAvatar extends StatelessWidget { /// Constructor for [ZetaAvatar] - /// [image] and [imageUrl] are used with [type] `ZetaAvatarType.image` - /// [initials] and [name] are used with [type] `ZetaAvatarType.initials` - /// If none provided, a placeholder is displayed, which defaults to `ZetaIcons.avatar`, - /// but can be customized via [placeholderIcon] and [placeholderColor]. - ZetaAvatar({ + const ZetaAvatar({ super.key, - required this.type, this.size = ZetaAvatarSize.xl, this.image, - this.imageUrl, this.initials, - this.name, this.backgroundColor, - this.placeholderIcon, - this.placeholderColor, - this.showStatus = false, - this.statusPrimaryColor, - this.statusSecondaryColor, - this.specialStatus, - this.badge, - }) { - _sizePixels = getSizePixels(size); - _borderSize = _getBorderSize(size); - _initialsToShow = - initials?.isEmpty ?? true ? _getInitialsFromName(name) : initials!.substring(0, initials!.length > 1 ? 2 : 1); - } - - /// Constructor for [ZetaAvatar] of type `image` - factory ZetaAvatar.image({ - ZetaAvatarSize size = ZetaAvatarSize.xl, - ImageProvider? image, - String? imageUrl, - String? initials, - String? name, - Color? backgroundColor, - Icon? placeholderIcon, - Color? placeholderColor, - bool showStatus = false, - Color? statusPrimaryColor, - Color? statusSecondaryColor, - ZetaIndicator? specialStatus, - ZetaIndicator? badge, - }) => - ZetaAvatar( - type: ZetaAvatarType.image, - size: size, - image: image, - imageUrl: imageUrl, - initials: initials, - name: name, - backgroundColor: backgroundColor, - placeholderIcon: placeholderIcon, - placeholderColor: placeholderColor, - showStatus: showStatus, - statusPrimaryColor: statusPrimaryColor, - statusSecondaryColor: statusSecondaryColor, - specialStatus: specialStatus, - badge: badge, - ); + this.lowerBadge, + this.upperBadge, + this.borderColor, + }); - /// Constructor for [ZetaAvatar] of type `initials` - factory ZetaAvatar.initials({ - ZetaAvatarSize size = ZetaAvatarSize.xl, - ImageProvider? image, - String? imageUrl, - String? initials, - String? name, - Color? backgroundColor, - Icon? placeholderIcon, - Color? placeholderColor, - bool showStatus = false, - Color? statusPrimaryColor, - Color? statusSecondaryColor, - ZetaIndicator? specialStatus, - ZetaIndicator? badge, - }) => - ZetaAvatar( - type: ZetaAvatarType.initials, - size: size, - image: image, - imageUrl: imageUrl, - initials: initials, - name: name, - backgroundColor: backgroundColor, - placeholderIcon: placeholderIcon, - placeholderColor: placeholderColor, - showStatus: showStatus, - statusPrimaryColor: statusPrimaryColor, - statusSecondaryColor: statusSecondaryColor, - specialStatus: specialStatus, - badge: badge, - ); + /// Constructor for [ZetaAvatar] with image. + const ZetaAvatar.image({ + super.key, + this.size = ZetaAvatarSize.xl, + this.image, + this.lowerBadge, + this.upperBadge, + this.borderColor, + }) : backgroundColor = null, + initials = null; + + /// Constructor for [ZetaAvatar] with initials. + const ZetaAvatar.initials({ + super.key, + required this.initials, + this.size = ZetaAvatarSize.xl, + this.lowerBadge, + this.upperBadge, + this.borderColor, + this.backgroundColor, + }) : image = null; - /// The type of the [ZetaAvatar] - image or initials - final ZetaAvatarType type; + /// Constructor for [ZetaAvatar] with initials from a full name. + ZetaAvatar.fromName({ + super.key, + required String name, + this.size = ZetaAvatarSize.xl, + this.lowerBadge, + this.upperBadge, + this.borderColor, + this.backgroundColor, + }) : image = null, + initials = name.initials; /// The size of the [ZetaAvatar] final ZetaAvatarSize size; - /// The `ImageProvider` for the type `image` - final ImageProvider? image; - - /// The URL for the type `image` - final String? imageUrl; + /// Image to display for avatar. + /// + /// [image] takes priority over [initials]. + final Widget? image; - /// The initials for the type `initials` + /// String to display initials. final String? initials; - /// Initials could be retrieved from `name` - final String? name; - /// Background color. final Color? backgroundColor; - /// Placeholder icon - final Icon? placeholderIcon; - - /// Placeholder color - final Color? placeholderColor; - /// Shows border around the avatar - /// See also [statusPrimaryColor] and [statusSecondaryColor] - final bool showStatus; - - /// Color for the outer border, if [showStatus] is `true` - final Color? statusPrimaryColor; - - /// Color for the inner border, if [showStatus] is `true` - final Color? statusSecondaryColor; + final Color? borderColor; - /// Show [ZetaIndicator] at the lower right corner - final ZetaIndicator? specialStatus; + /// Status badge shown at lower right corner of avatar. + final ZetaIndicator? lowerBadge; - /// Show [ZetaIndicator] at the upper right corner - final ZetaIndicator? badge; + /// Notification Badge shown at top right corner of avatar. + final ZetaIndicator? upperBadge; - late final double _sizePixels; - late final double _borderSize; - late final String _initialsToShow; + bool get _showPlaceholder => image == null && (initials == null || initials!.isEmpty); @override Widget build(BuildContext context) { final zetaColors = Zeta.of(context).colors; - final innerContent = _InnerContent( - type: type, - size: size, - sizePixels: _sizePixels, - borderSize: _borderSize, - image: image, - imageUrl: imageUrl, - initials: _initialsToShow, - showStatus: showStatus, - placeholderIcon: placeholderIcon, - placeholderColor: placeholderColor, + final borderSize = size.borderSize; + final sizePixels = size.pixelSize; + final contentSizePixels = size.pixelSize - (borderColor != null ? size.borderSize * 2 : 0); + + final innerContent = ClipRRect( + borderRadius: BorderRadius.circular(64), + clipBehavior: Clip.hardEdge, + child: image ?? + (_showPlaceholder + ? Container( + transform: Matrix4.translationValues(-contentSizePixels * 0.2, -contentSizePixels * 0.1, 0), + child: IconTheme( + data: IconThemeData( + color: Zeta.of(context).colors.cool, + size: contentSizePixels * 1.4, + ), + child: const Icon(ZetaIcons.user_round), + ), + ) + : Center( + child: Text( + size == ZetaAvatarSize.xs ? initials!.substring(0, 1) : initials!, + style: TextStyle(fontSize: size.fontSize, letterSpacing: -0.5), + ), + )), ); return Stack( children: [ - if (showStatus) - Container( - margin: EdgeInsets.all(badge == null && specialStatus == null ? 0 : 3), - width: _sizePixels, - height: _sizePixels, - decoration: BoxDecoration( - border: Border.all( - color: statusPrimaryColor ?? zetaColors.positive, - width: _borderSize, - ), - borderRadius: BorderRadius.circular(64), - ), - child: Container( - width: _sizePixels - _borderSize * 2, - height: _sizePixels - _borderSize * 2, - decoration: BoxDecoration( - color: type == ZetaAvatarType.initials && _initialsToShow.isNotEmpty - ? backgroundColor ?? zetaColors.surfaceHovered - : null, - border: Border.all( - color: statusSecondaryColor ?? zetaColors.surfacePrimary, - width: _borderSize, - ), - borderRadius: BorderRadius.circular(64), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(64), - clipBehavior: Clip.hardEdge, - child: innerContent, - ), - ), - ) - else - Container( - margin: EdgeInsets.all(badge == null && specialStatus == null ? 0 : 3), - width: _sizePixels, - height: _sizePixels, - decoration: BoxDecoration( - color: backgroundColor ?? zetaColors.surfaceHovered, - borderRadius: BorderRadius.circular(64), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(64), - clipBehavior: Clip.hardEdge, - child: innerContent, - ), + Container( + margin: EdgeInsets.all(upperBadge == null && lowerBadge == null ? 0 : 3), + width: sizePixels, + height: sizePixels, + decoration: BoxDecoration( + border: borderColor != null ? Border.all(color: borderColor!, width: borderSize / ZetaSpacing.x0_5) : null, + borderRadius: ZetaRadius.full, + color: backgroundColor ?? (_showPlaceholder ? zetaColors.surfacePrimary : zetaColors.cool.shade20), + ), + child: borderColor != null + ? Container( + width: contentSizePixels, + height: contentSizePixels, + decoration: BoxDecoration( + color: _showPlaceholder ? backgroundColor ?? zetaColors.surfaceHovered : null, + border: Border.all(color: zetaColors.surfacePrimary, width: borderSize / ZetaSpacing.x0_5), + borderRadius: ZetaRadius.full, + ), + child: ClipRRect(borderRadius: ZetaRadius.full, clipBehavior: Clip.hardEdge, child: innerContent), + ) + : innerContent, + ), + if (upperBadge != null) + Positioned( + right: 1, + child: upperBadge!.copyWith(size: size.indicatorSize), + ), + if (lowerBadge != null) + Positioned( + right: 1, + bottom: 1, + child: lowerBadge!.copyWith(size: size.indicatorSize), ), - if (badge != null) Positioned(right: 1, child: badge!), - if (specialStatus != null) Positioned(right: 1, bottom: 1, child: specialStatus!), ], ); } - /// Returns the size of [ZetaAvatarSize] in pixels - static double getSizePixels(ZetaAvatarSize size) { - switch (size) { + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('size', size)) + ..add(DiagnosticsProperty('name', initials)) + ..add(DiagnosticsProperty('specialStatus', lowerBadge)) + ..add(DiagnosticsProperty('badge', upperBadge)) + ..add(DiagnosticsProperty('backgroundColor', backgroundColor)) + ..add(ColorProperty('statusColor', borderColor)); + } +} + +extension on ZetaAvatarSize { + double get pixelSize { + switch (this) { case ZetaAvatarSize.xl: - return 64; + return ZetaSpacing.x16; case ZetaAvatarSize.l: - return 48; + return ZetaSpacing.x12; case ZetaAvatarSize.m: - return 40; + return ZetaSpacing.x10; case ZetaAvatarSize.s: - return 32; + return ZetaSpacing.x8; case ZetaAvatarSize.xs: - return 24; + return ZetaSpacing.x6; } } - double _getBorderSize(ZetaAvatarSize size) { - switch (size) { + ZetaWidgetSize get indicatorSize { + switch (this) { case ZetaAvatarSize.xl: - return 2; case ZetaAvatarSize.l: - return 2; case ZetaAvatarSize.m: - return 1.67; + return ZetaWidgetSize.large; case ZetaAvatarSize.s: - return 1.33; + return ZetaWidgetSize.medium; + case ZetaAvatarSize.xs: - return 1; + return ZetaWidgetSize.small; } } - String _getInitialsFromName(String? name) { - if (name == null) return ''; - final List nameParts = name.split(RegExp(r'\W+'))..removeWhere((item) => item.isEmpty); - if (nameParts.isEmpty) return ''; - return (nameParts.length > 1 - ? nameParts[0].substring(0, 1) + nameParts[1].substring(0, 1) - : nameParts[0].length > 1 - ? nameParts[0].substring(0, 2) - : nameParts[0]) - .toUpperCase(); - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', type)) - ..add(DiagnosticsProperty('size', size)) - ..add(DiagnosticsProperty('image', image)) - ..add(DiagnosticsProperty('imageUrl', imageUrl)) - ..add(DiagnosticsProperty('initials', initials)) - ..add(DiagnosticsProperty('name', name)) - ..add(DiagnosticsProperty('showStatus', showStatus)) - ..add(DiagnosticsProperty('specialStatus', specialStatus)) - ..add(DiagnosticsProperty('badge', badge)) - ..add(DiagnosticsProperty('placeholderIcon', placeholderIcon)) - ..add(DiagnosticsProperty('backgroundColor', backgroundColor)) - ..add(DiagnosticsProperty('placeholderColor', placeholderColor)) - ..add(DiagnosticsProperty('statusPrimaryColor', statusPrimaryColor)) - ..add(DiagnosticsProperty('statusSecondaryColor', statusSecondaryColor)); - } -} - -class _InnerContent extends StatelessWidget { - const _InnerContent({ - required this.type, - required this.size, - required this.sizePixels, - required this.borderSize, - required this.initials, - this.image, - this.imageUrl, - this.showStatus = false, - this.placeholderIcon, - this.placeholderColor, - }); - - final ZetaAvatarType type; - final ZetaAvatarSize size; - final double sizePixels; - final double borderSize; - final String initials; - final ImageProvider? image; - final String? imageUrl; - final bool showStatus; - final Icon? placeholderIcon; - final Color? placeholderColor; - - @override - Widget build(BuildContext context) { - final placeholder = IconTheme( - data: IconThemeData( - color: placeholderColor ?? Zeta.of(context).colors.cool, - size: showStatus ? sizePixels - borderSize * 4 : sizePixels, - ), - child: placeholderIcon ?? const Icon(ZetaIcons.avatar), - ); + double get borderSize { + switch (this) { + case ZetaAvatarSize.xl: + case ZetaAvatarSize.l: + case ZetaAvatarSize.m: + return ZetaSpacing.x1; - switch (type) { - case ZetaAvatarType.image: - return image == null - ? imageUrl == null - ? placeholder - : CachedNetworkImage( - imageUrl: imageUrl!, - fit: BoxFit.cover, - placeholder: (_, __) => placeholder, - errorWidget: (_, __, ___) => placeholder, - ) - : Image(image: image!, fit: BoxFit.cover); - case ZetaAvatarType.initials: - return initials.isEmpty - ? placeholder - : Center( - child: Text( - size == ZetaAvatarSize.xs ? initials.substring(0, 1) : initials, - style: TextStyle( - fontSize: _getFontSize(size), - letterSpacing: -0.5, - ), - ), - ); + case ZetaAvatarSize.s: + case ZetaAvatarSize.xs: + return ZetaSpacing.x0_5; } } - double _getFontSize(ZetaAvatarSize size) { - switch (size) { + double get fontSize { + switch (this) { case ZetaAvatarSize.xl: - return 28; + return ZetaSpacing.x5; case ZetaAvatarSize.l: - return 24; + return ZetaSpacing.x4; case ZetaAvatarSize.m: - return 20; + return ZetaSpacing.x3_5; case ZetaAvatarSize.s: - return 16; case ZetaAvatarSize.xs: - return 16; + return ZetaSpacing.x3; } } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', type)) - ..add(DiagnosticsProperty('size', size)) - ..add(DiagnosticsProperty('sizePixels', sizePixels)) - ..add(DiagnosticsProperty('borderSize', borderSize)) - ..add(DiagnosticsProperty('image', image)) - ..add(DiagnosticsProperty('imageUrl', imageUrl)) - ..add(DiagnosticsProperty('initials', initials)) - ..add(DiagnosticsProperty('showStatus', showStatus)) - ..add(DiagnosticsProperty('placeholderIcon', placeholderIcon)) - ..add(DiagnosticsProperty('placeholderColor', placeholderColor)); - } } diff --git a/lib/src/components/badges/badge.dart b/lib/src/components/badges/badge.dart index c302bdb4..b4fa87d8 100644 --- a/lib/src/components/badges/badge.dart +++ b/lib/src/components/badges/badge.dart @@ -33,7 +33,7 @@ class ZetaBadge extends StatelessWidget { final Color backgroundColor = status.colorSwatch(context); return Container( - padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x1, vertical: ZetaSpacing.x1 / 2), + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x1, vertical: ZetaSpacing.x0_5), decoration: BoxDecoration( color: backgroundColor, borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.minimal, diff --git a/lib/src/components/badges/indicator.dart b/lib/src/components/badges/indicator.dart index 084803bb..52785236 100644 --- a/lib/src/components/badges/indicator.dart +++ b/lib/src/components/badges/indicator.dart @@ -11,65 +11,43 @@ enum ZetaIndicatorType { notification, } -/// [ZetaIndicator] size. -enum ZetaIndicatorSize { - /// Largest size - [ZetaSpacing.x4] 16x16 pixels. - large, - - /// Medium size - [ZetaSpacing.x3] - 12x12 pixels for [ZetaIndicatorType.icon] or [ZetaSpacing.x3_5] - 14x14 pixels for [ZetaIndicatorType.notification]. - medium, - - /// Smallest size - [ZetaSpacing.x2] - 8x8 pixels. - small, -} - /// ZetaIndicator. /// /// Indicators are used to show the status of a user or any messages/notifications they might have. class ZetaIndicator extends StatelessWidget { /// Constructor for [ZetaIndicator]. - ZetaIndicator({ + const ZetaIndicator({ super.key, required this.type, - this.size = ZetaIndicatorSize.large, + this.size = ZetaWidgetSize.large, this.icon, this.value, this.inverse = false, - }) { - _sizePixels = _getSizePixels(size, type); - } + }); /// Constructor for [ZetaIndicator] of type [ZetaIndicatorType.icon]. - factory ZetaIndicator.icon({ - ZetaIndicatorSize size = ZetaIndicatorSize.large, - bool inverseBorder = false, - Icon? icon, - }) => - ZetaIndicator( - type: ZetaIndicatorType.icon, - size: size, - inverse: inverseBorder, - icon: icon, - ); + const ZetaIndicator.icon({ + super.key, + this.size = ZetaWidgetSize.large, + this.inverse = false, + this.icon, + }) : type = ZetaIndicatorType.icon, + value = null; /// Constructor for [ZetaIndicator] of type [ZetaIndicatorType.notification]. - factory ZetaIndicator.notification({ - ZetaIndicatorSize size = ZetaIndicatorSize.large, - bool inverseBorder = false, - int? value, - }) => - ZetaIndicator( - type: ZetaIndicatorType.notification, - size: size, - inverse: inverseBorder, - value: value, - ); + const ZetaIndicator.notification({ + super.key, + this.size = ZetaWidgetSize.large, + this.inverse = false, + this.icon, + this.value, + }) : type = ZetaIndicatorType.notification; /// The type of the [ZetaIndicator] - icon or notification. final ZetaIndicatorType type; - /// The size of the [ZetaIndicator]. Default is [ZetaIndicatorSize.large] - final ZetaIndicatorSize size; + /// The size of the [ZetaIndicator]. Default is [ZetaWidgetSize.large] + final ZetaWidgetSize size; /// Inverse the border color. final bool inverse; @@ -80,30 +58,46 @@ class ZetaIndicator extends StatelessWidget { /// Value for the type `notification`. final int? value; - late final double _sizePixels; + /// Creates a clone. + ZetaIndicator copyWith({ + ZetaIndicatorType? type, + ZetaWidgetSize? size, + Icon? icon, + int? value, + bool? inverse, + }) { + return ZetaIndicator( + type: type ?? this.type, + size: size ?? this.size, + icon: icon ?? this.icon, + value: value ?? this.value, + inverse: inverse ?? this.inverse, + ); + } @override Widget build(BuildContext context) { final zetaColors = Zeta.of(context).colors; final Color backgroundColor = (type == ZetaIndicatorType.icon ? zetaColors.blue : zetaColors.negative); final Color foregroundColor = backgroundColor.onColor; + final sizePixels = _getSizePixels(size, type); return Container( - width: _sizePixels + ZetaSpacing.x1, - height: _sizePixels + ZetaSpacing.x1, + width: sizePixels + ZetaSpacing.x1, + height: sizePixels + ZetaSpacing.x1, decoration: BoxDecoration( color: (inverse ? foregroundColor : Colors.transparent), - borderRadius: BorderRadius.circular(20), + borderRadius: ZetaRadius.full, ), child: Center( child: Container( - width: _sizePixels, - height: _sizePixels, + width: sizePixels, + height: sizePixels, decoration: BoxDecoration(color: backgroundColor, borderRadius: BorderRadius.circular(ZetaSpacing.x4)), child: ClipRRect( borderRadius: BorderRadius.circular(ZetaSpacing.x4), clipBehavior: Clip.hardEdge, - child: size == ZetaIndicatorSize.small ? null : _buildContent(foregroundColor), + child: size == ZetaWidgetSize.small ? null : _buildContent(foregroundColor), ), ), ), @@ -124,33 +118,33 @@ class ZetaIndicator extends StatelessWidget { return Center( child: Text( value.formatMaxChars(), - style: (size == ZetaIndicatorSize.large ? ZetaTextStyles.labelIndicator : ZetaTextStyles.labelTiny) + style: (size == ZetaWidgetSize.large ? ZetaTextStyles.labelIndicator : ZetaTextStyles.labelTiny) .apply(color: foregroundColor), ), ); } } - /// Returns the size of [ZetaIndicatorSize] in pixels - double _getSizePixels(ZetaIndicatorSize size, ZetaIndicatorType type) { + /// Returns the size of [ZetaWidgetSize] in pixels. + double _getSizePixels(ZetaWidgetSize size, ZetaIndicatorType type) { switch (size) { - case ZetaIndicatorSize.large: + case ZetaWidgetSize.large: return ZetaSpacing.x4; - case ZetaIndicatorSize.medium: + case ZetaWidgetSize.medium: return type == ZetaIndicatorType.icon ? ZetaSpacing.x3 : ZetaSpacing.x3_5; - case ZetaIndicatorSize.small: + case ZetaWidgetSize.small: return ZetaSpacing.x2; } } - double _getIconSize(ZetaIndicatorSize size) { + double _getIconSize(ZetaWidgetSize size) { switch (size) { - case ZetaIndicatorSize.large: + case ZetaWidgetSize.large: return ZetaSpacing.x3; - case ZetaIndicatorSize.medium: + case ZetaWidgetSize.medium: return ZetaSpacing.x2; - case ZetaIndicatorSize.small: - return ZetaSpacing.x0; + case ZetaWidgetSize.small: + return 0; } } @@ -159,7 +153,7 @@ class ZetaIndicator extends StatelessWidget { super.debugFillProperties(properties); properties ..add(DiagnosticsProperty('type', type)) - ..add(DiagnosticsProperty('size', size)) + ..add(DiagnosticsProperty('size', size)) ..add(DiagnosticsProperty('value', value)) ..add(DiagnosticsProperty('icon', icon)) ..add(DiagnosticsProperty('inverseBorder', inverse)); diff --git a/lib/src/components/badges/status_label.dart b/lib/src/components/badges/status_label.dart index 0da9ce8f..e403d0a2 100644 --- a/lib/src/components/badges/status_label.dart +++ b/lib/src/components/badges/status_label.dart @@ -16,7 +16,7 @@ class ZetaStatusLabel extends StatelessWidget { this.customIcon, }); - /// {@zeta-component-rounded} + /// {@macro zeta-component-rounded} final bool rounded; /// {@macro zeta-component-badge-status} @@ -39,7 +39,7 @@ class ZetaStatusLabel extends StatelessWidget { borderRadius: rounded ? ZetaRadius.full : ZetaRadius.minimal, ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x2, vertical: ZetaSpacing.x1 / 2), + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x2, vertical: ZetaSpacing.x0_5), child: Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/src/components/badges/tag.dart b/lib/src/components/badges/tag.dart index 09367596..877141ab 100644 --- a/lib/src/components/badges/tag.dart +++ b/lib/src/components/badges/tag.dart @@ -23,25 +23,10 @@ class ZetaTag extends StatelessWidget { }); /// Constructs left facing [ZetaTag]. - factory ZetaTag.left({ - required String label, - bool rounded = true, - }) => - ZetaTag( - label: label, - rounded: rounded, - ); + const ZetaTag.left({super.key, required this.label, this.rounded = true}) : direction = ZetaTagDirection.left; ///Constructs right facing [ZetaTag]. - factory ZetaTag.right({ - required String label, - bool rounded = true, - }) => - ZetaTag( - direction: ZetaTagDirection.right, - rounded: rounded, - label: label, - ); + const ZetaTag.right({super.key, required this.label, this.rounded = true}) : direction = ZetaTagDirection.right; ///Determines the direction of the tag /// @@ -91,13 +76,13 @@ class ZetaTag extends StatelessWidget { if (!rounded) return null; if (direction == ZetaTagDirection.right) { return const BorderRadius.only( - topRight: Radius.circular(2), - bottomRight: Radius.circular(2), + topRight: Radius.circular(ZetaSpacing.x0_5), + bottomRight: Radius.circular(ZetaSpacing.x0_5), ); } else { return const BorderRadius.only( - topLeft: Radius.circular(2), - bottomLeft: Radius.circular(2), + topLeft: Radius.circular(ZetaSpacing.x0_5), + bottomLeft: Radius.circular(ZetaSpacing.x0_5), ); } } diff --git a/lib/src/components/banners/in_page_banner.dart b/lib/src/components/banners/in_page_banner.dart index f5b955ea..227703be 100644 --- a/lib/src/components/banners/in_page_banner.dart +++ b/lib/src/components/banners/in_page_banner.dart @@ -10,70 +10,68 @@ class ZetaInPageBanner extends StatelessWidget { super.key, required this.content, this.rounded = true, - this.severity = ZetaWidgetStatus.info, - this.showIconClose = true, + this.status = ZetaWidgetStatus.info, this.onClose, this.title, this.customIcon, this.actions = const [], }); - ///The content of the banner + ///The content of the banner. Typically [Text]. final Widget content; /// {@macro zeta-component-rounded} final bool rounded; - ///Determines the color of the banner - ///Defaults to 'neutral' - final ZetaWidgetStatus severity; + ///Determines the color of the banner. + /// + ///Defaults to [ZetaWidgetStatus.info]. + final ZetaWidgetStatus status; - ///Determines if the banner has icon for closing - ///Defaults to true - final bool showIconClose; - - ///Title of the banner + ///Title of the banner. final String? title; - ///Custom icon + /// Leading icon on top left of banner. final IconData? customIcon; /// Action buttons to show at the bottom of the banner. final List actions; - ///Called when the button 'Close' is tapped. + /// Called when the button 'Close' is tapped. + /// + /// If null, close icon will not appear. final VoidCallback? onClose; @override Widget build(BuildContext context) { final theme = Zeta.of(context); - final colors = _getColors(theme); + final colors = status.colorSwatch(context); final hasTitle = title != null; return DecoratedBox( decoration: BoxDecoration( - color: colors.backgroundColor, - border: Border.all(color: colors.foregroundColor), + color: colors.surface, + border: Border.all(color: colors.border), borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, ), child: Padding( - padding: const EdgeInsets.all(2), + padding: const EdgeInsets.all(ZetaSpacing.x0_5), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsetsDirectional.only(top: 12, start: 10), + padding: const EdgeInsetsDirectional.only(top: ZetaSpacing.x3, start: ZetaSpacing.x2_5), child: Icon( - severity.icon(rounded: rounded), + status.icon(rounded: rounded), size: ZetaSpacing.x5, - color: severity == ZetaWidgetStatus.neutral ? theme.colors.textDefault : colors.foregroundColor, + color: status == ZetaWidgetStatus.neutral ? theme.colors.textDefault : colors.icon, ), ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox(height: 10), + const SizedBox(height: ZetaSpacing.x2_5), if (hasTitle) Text( title!, @@ -90,11 +88,11 @@ class ZetaInPageBanner extends StatelessWidget { .divide(const SizedBox.square(dimension: ZetaSpacing.x2)) .toList(), ).paddingTop(ZetaSpacing.x4), - const SizedBox(height: 10), + const SizedBox(height: ZetaSpacing.x2_5), ], ), ), - if (showIconClose) + if (onClose != null) IconButton( onPressed: onClose, icon: Icon( @@ -108,37 +106,6 @@ class ZetaInPageBanner extends StatelessWidget { ); } - ZetaWidgetColor _getColors(Zeta theme) { - final defaultColorScheme = ZetaWidgetColor( - backgroundColor: theme.colors.surfacePrimary, - foregroundColor: theme.colors.borderDefault, - ); - switch (severity) { - case ZetaWidgetStatus.neutral: - return defaultColorScheme; - case ZetaWidgetStatus.info: - return ZetaWidgetColor( - backgroundColor: theme.colors.info.surface, - foregroundColor: theme.colors.info.border, - ); - case ZetaWidgetStatus.positive: - return ZetaWidgetColor( - backgroundColor: theme.colors.positive.surface, - foregroundColor: theme.colors.positive.border, - ); - case ZetaWidgetStatus.warning: - return ZetaWidgetColor( - backgroundColor: theme.colors.warning.surface.lighten(6), - foregroundColor: theme.colors.warning.border, - ); - case ZetaWidgetStatus.negative: - return ZetaWidgetColor( - backgroundColor: theme.colors.negative.surface, - foregroundColor: theme.colors.negative.border, - ); - } - } - @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); @@ -150,8 +117,7 @@ class ZetaInPageBanner extends StatelessWidget { ), ) ..add(DiagnosticsProperty('rounded', rounded)) - ..add(EnumProperty('severity', severity)) - ..add(DiagnosticsProperty('showIconClose', showIconClose)) + ..add(EnumProperty('severity', status)) ..add(StringProperty('title', title)) ..add(DiagnosticsProperty('customIcon', customIcon)); } diff --git a/lib/src/components/bottom sheets/bottom_sheet.dart b/lib/src/components/bottom sheets/bottom_sheet.dart index 44dfaef8..9af8c853 100644 --- a/lib/src/components/bottom sheets/bottom_sheet.dart +++ b/lib/src/components/bottom sheets/bottom_sheet.dart @@ -9,53 +9,50 @@ class ZetaBottomSheet extends StatelessWidget { const ZetaBottomSheet({ super.key, this.title, - this.titleAlignment, this.body, - this.horizontalAlignment, + this.centerTitle = true, }); /// The title of [ZetaBottomSheet]. final String? title; - /// The alignment of the title. - /// Default is `Alignment.center` - final AlignmentGeometry? titleAlignment; + /// Whether title should be center or left aligned. + /// + /// Defaults to true (center aligned). + final bool centerTitle; /// The content of [ZetaBottomSheet]. final Widget? body; - /// The horizontal alignment of the [ZetaBottomSheet]'s content. - final CrossAxisAlignment? horizontalAlignment; - @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - final themeMode = Zeta.of(context).themeMode; - final isDark = themeMode == ThemeMode.dark || - (themeMode == ThemeMode.system && PlatformDispatcher.instance.platformBrightness == Brightness.dark); return Container( - width: double.infinity, - padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), + padding: const EdgeInsets.fromLTRB( + ZetaSpacing.x5, + 0, + ZetaSpacing.x5, + ZetaSpacing.x5, + ), decoration: BoxDecoration( - color: isDark ? colors.cool.shade20 : colors.surfacePrimary, + color: colors.surfaceSecondary, borderRadius: const BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20), + topLeft: Radius.circular(ZetaSpacing.x6), + topRight: Radius.circular(ZetaSpacing.x6), ), ), child: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: horizontalAlignment ?? CrossAxisAlignment.center, children: [ Align( child: SizedBox( - height: 36, + height: ZetaSpacing.x9, child: Padding( - padding: const EdgeInsets.only(top: 8), + padding: const EdgeInsets.only(top: ZetaSpacing.x2), child: Icon( Icons.maximize_rounded, - size: 60, + size: ZetaSpacing.x16, color: colors.surfaceDisabled, ), ), @@ -63,13 +60,13 @@ class ZetaBottomSheet extends StatelessWidget { ), if (title != null) Align( - alignment: titleAlignment ?? Alignment.center, + alignment: centerTitle ? Alignment.center : Alignment.centerLeft, child: Text( title!, style: ZetaTextStyles.titleMedium, ), ), - body ?? const SizedBox(), + Material(child: body ?? const SizedBox()), ], ), ); @@ -80,7 +77,29 @@ class ZetaBottomSheet extends StatelessWidget { super.debugFillProperties(properties); properties ..add(DiagnosticsProperty('title', title)) - ..add(DiagnosticsProperty('titleAlignment', titleAlignment)) - ..add(EnumProperty('horizontalAlignment', horizontalAlignment)); + ..add(DiagnosticsProperty('centerTitle', centerTitle)); } } + +/// Function to show [ZetaBottomSheet]. +/// +/// Uses [showModalBottomSheet] for functionality, but with Zeta styling and simplified functionality. +Future showZetaBottomSheet({ + required BuildContext context, + String? title, + Widget? body, + bool centerTitle = true, + bool isDismissible = true, + bool enableDrag = true, +}) { + return showModalBottomSheet( + context: context, + isDismissible: isDismissible, + enableDrag: enableDrag, + builder: (BuildContext context) => ZetaBottomSheet( + title: title, + body: body, + centerTitle: centerTitle, + ), + ); +} diff --git a/lib/src/components/bottom sheets/menu_items.dart b/lib/src/components/bottom sheets/menu_items.dart index 211fe89e..750c3ed7 100644 --- a/lib/src/components/bottom sheets/menu_items.dart +++ b/lib/src/components/bottom sheets/menu_items.dart @@ -11,118 +11,101 @@ enum ZetaMenuItemType { vertical, } -/// Component [ZetaMenuItem]. -/// It can be horizontal or vertical +/// Zeta Menu Item component. +/// +/// Typically used as body of [ZetaBottomSheet]. class ZetaMenuItem extends StatelessWidget { - /// Constructor for the component [ZetaMenuItem] + /// Constructor for the component [ZetaMenuItem]. + /// + /// Typically, [ZetaMenuItem.horizontal] or [ZetaMenuItem.vertical] constructors should be used. const ZetaMenuItem({ super.key, required this.type, required this.label, this.onTap, - this.leadingIcon, - this.trailingIcon, - this.showTrailing = false, - this.disabled = false, + this.leading, + this.trailing, }); /// Creates horizontal menu item - factory ZetaMenuItem.horizontal({ - required Widget label, - VoidCallback? onTap, - Widget? leadingIcon, - Widget? trailingIcon, - bool showTrailing = false, - bool disabled = false, - }) { - return ZetaMenuItem( - type: ZetaMenuItemType.horizontal, - label: label, - onTap: onTap, - leadingIcon: leadingIcon, - trailingIcon: trailingIcon, - showTrailing: showTrailing, - disabled: disabled, - ); - } + const ZetaMenuItem.horizontal({ + super.key, + required this.label, + this.onTap, + this.leading, + this.trailing, + }) : type = ZetaMenuItemType.horizontal; /// Creates horizontal menu item - factory ZetaMenuItem.vertical({ - required Widget label, - required Widget icon, - VoidCallback? onTap, - bool disabled = false, - }) { - return ZetaMenuItem( - type: ZetaMenuItemType.vertical, - label: label, - onTap: onTap, - leadingIcon: icon, - disabled: disabled, - ); - } + const ZetaMenuItem.vertical({ + super.key, + required this.label, + Widget? icon, + this.onTap, + }) : type = ZetaMenuItemType.vertical, + leading = icon, + trailing = null; - /// The type of the [ZetaMenuItem] - horizontal or vertical + /// The type of the [ZetaMenuItem] - horizontal or vertical. final ZetaMenuItemType type; /// What to do when [ZetaMenuItem] is pressed. final VoidCallback? onTap; - /// The label of the [ZetaMenuItem] + /// The label of the [ZetaMenuItem]. final Widget label; - /// The leading icon of the [ZetaMenuItem] - final Widget? leadingIcon; + /// The leading widget of the [ZetaMenuItem]. + /// + /// Icon is at leading edge for [ZetaMenuItem.horizontal], and center aligned for [ZetaMenuItem.vertical]. + /// + /// Typically an [Icon]. + final Widget? leading; - /// The trailing icon of the [ZetaMenuItem] - final Widget? trailingIcon; + /// The trailing widget of the [ZetaMenuItem]. + /// + /// Only used for [ZetaMenuItem.horizontal]. + /// + /// Typically an icon. + final Widget? trailing; - /// Determines whether to show the trailing icon. - /// Default is false. - final bool showTrailing; + bool get _enabled => onTap != null; - /// Sets disabled state of [ZetaMenuItem] - /// Default is false - final bool disabled; + VoidCallback? get _onTap => _enabled ? onTap : null; @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; + + final Widget text = DefaultTextStyle( + style: ZetaTextStyles.labelLarge.apply(color: _enabled ? colors.textDefault : colors.textDisabled), + child: label, + ); + switch (type) { case ZetaMenuItemType.horizontal: return ConstrainedBox( - constraints: const BoxConstraints(minHeight: 48), + constraints: const BoxConstraints(minHeight: ZetaSpacing.x12), child: InkWell( - onTap: disabled ? null : onTap, + onTap: _onTap, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x4, vertical: ZetaSpacing.x3), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Row( children: [ - if (leadingIcon != null) - Padding( - padding: const EdgeInsets.only(right: 10), - child: IconTheme( - data: _iconThemeData(colors, disabled, 24), - child: leadingIcon!, - ), - ), - Expanded( - child: DefaultTextStyle( - style: _defaultTextStyle(colors, disabled), - child: label, - ), - ), + if (leading != null) + Padding(padding: const EdgeInsets.only(right: ZetaSpacing.x2), child: leading), + Expanded(child: text), ], ), ), - if (showTrailing || trailingIcon != null) + if (trailing != null) IconTheme( - data: _iconThemeData(colors, disabled, 24), - child: trailingIcon ?? const Icon(Icons.keyboard_arrow_right), + data: _iconThemeData(colors, _enabled, ZetaSpacing.x6), + child: trailing ?? const Icon(Icons.keyboard_arrow_right), ), ], ), @@ -131,23 +114,20 @@ class ZetaMenuItem extends StatelessWidget { ); case ZetaMenuItemType.vertical: return InkWell( - onTap: disabled ? null : onTap, + onTap: _onTap, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x4, vertical: ZetaSpacing.x3), child: Column( children: [ - if (leadingIcon != null) + if (leading != null) Padding( - padding: const EdgeInsets.only(bottom: 10), + padding: const EdgeInsets.only(bottom: ZetaSpacing.x3), child: IconTheme( - data: _iconThemeData(colors, disabled, 32), - child: leadingIcon!, + data: _iconThemeData(colors, _enabled, ZetaSpacing.x8), + child: leading!, ), ), - DefaultTextStyle( - style: _defaultTextStyle(colors, disabled), - child: label, - ), + text, ], ), ), @@ -155,12 +135,8 @@ class ZetaMenuItem extends StatelessWidget { } } - static TextStyle _defaultTextStyle(ZetaColors colors, bool disabled) => ZetaTextStyles.labelLarge.apply( - color: disabled ? colors.textDisabled : colors.textDefault, - ); - - static IconThemeData _iconThemeData(ZetaColors colors, bool disabled, double size) => IconThemeData( - color: disabled ? colors.iconDisabled : colors.iconSubtle, + static IconThemeData _iconThemeData(ZetaColors colors, bool enabled, double size) => IconThemeData( + color: enabled ? colors.iconSubtle : colors.iconDisabled, size: size, ); @@ -169,8 +145,6 @@ class ZetaMenuItem extends StatelessWidget { super.debugFillProperties(properties); properties ..add(DiagnosticsProperty('type', type)) - ..add(DiagnosticsProperty('disabled', disabled)) - ..add(DiagnosticsProperty('showTrailing', showTrailing)) ..add(DiagnosticsProperty('onTap', onTap)); } } diff --git a/lib/src/components/buttons/button.dart b/lib/src/components/buttons/button.dart index 3395ad6c..70ae5644 100644 --- a/lib/src/components/buttons/button.dart +++ b/lib/src/components/buttons/button.dart @@ -57,14 +57,14 @@ extension on ZetaButtonType { bool get solid => index < 4; } -extension on BorderType { +extension on ZetaWidgetBorder { BorderRadius get radius { switch (this) { - case BorderType.sharp: + case ZetaWidgetBorder.sharp: return ZetaRadius.none; - case BorderType.rounded: + case ZetaWidgetBorder.rounded: return ZetaRadius.minimal; - case BorderType.full: + case ZetaWidgetBorder.full: return ZetaRadius.full; } } @@ -78,7 +78,7 @@ class ZetaButton extends StatelessWidget { this.onPressed, this.type = ZetaButtonType.primary, this.size = ZetaWidgetSize.medium, - this.borderType = BorderType.rounded, + this.borderType = ZetaWidgetBorder.rounded, super.key, }); @@ -87,7 +87,7 @@ class ZetaButton extends StatelessWidget { required this.label, this.onPressed, this.size = ZetaWidgetSize.medium, - this.borderType = BorderType.rounded, + this.borderType = ZetaWidgetBorder.rounded, super.key, }) : type = ZetaButtonType.primary; @@ -96,7 +96,7 @@ class ZetaButton extends StatelessWidget { required this.label, this.onPressed, this.size = ZetaWidgetSize.medium, - this.borderType = BorderType.rounded, + this.borderType = ZetaWidgetBorder.rounded, super.key, }) : type = ZetaButtonType.secondary; @@ -105,7 +105,7 @@ class ZetaButton extends StatelessWidget { required this.label, this.onPressed, this.size = ZetaWidgetSize.medium, - this.borderType = BorderType.rounded, + this.borderType = ZetaWidgetBorder.rounded, super.key, }) : type = ZetaButtonType.positive; @@ -114,7 +114,7 @@ class ZetaButton extends StatelessWidget { required this.label, this.onPressed, this.size = ZetaWidgetSize.medium, - this.borderType = BorderType.rounded, + this.borderType = ZetaWidgetBorder.rounded, super.key, }) : type = ZetaButtonType.negative; @@ -123,7 +123,7 @@ class ZetaButton extends StatelessWidget { required this.label, this.onPressed, this.size = ZetaWidgetSize.medium, - this.borderType = BorderType.rounded, + this.borderType = ZetaWidgetBorder.rounded, super.key, }) : type = ZetaButtonType.outline; @@ -132,7 +132,7 @@ class ZetaButton extends StatelessWidget { required this.label, this.onPressed, this.size = ZetaWidgetSize.medium, - this.borderType = BorderType.rounded, + this.borderType = ZetaWidgetBorder.rounded, super.key, }) : type = ZetaButtonType.outlineSubtle; @@ -141,7 +141,7 @@ class ZetaButton extends StatelessWidget { required this.label, this.onPressed, this.size = ZetaWidgetSize.medium, - this.borderType = BorderType.rounded, + this.borderType = ZetaWidgetBorder.rounded, super.key, }) : type = ZetaButtonType.text; @@ -156,18 +156,18 @@ class ZetaButton extends StatelessWidget { ///Whether or not the button is sharp or rounded ///Defaults to rounded - final BorderType borderType; + final ZetaWidgetBorder borderType; /// Size of the button. Defaults to large. final ZetaWidgetSize size; - /// Creates a clone + /// Creates a clone. ZetaButton copyWith({ String? label, VoidCallback? onPressed, ZetaButtonType? type, ZetaWidgetSize? size, - BorderType? borderType, + ZetaWidgetBorder? borderType, Key? key, }) { return ZetaButton( @@ -241,18 +241,17 @@ class ZetaButton extends StatelessWidget { return null; }), side: MaterialStateProperty.resolveWith((Set states) { - if (type.border) { - if (states.contains(MaterialState.disabled)) { - return BorderSide(color: colors.cool.shade40); - } - - return BorderSide(color: type == ZetaButtonType.outline ? colors.primary.border : colors.borderDefault); + if (type.border && states.contains(MaterialState.disabled)) { + return BorderSide(color: colors.cool.shade40); } - // TODO(thelukewalton): This removes a defualt border when focused, rather than adding a second border when focused. if (states.contains(MaterialState.focused)) { - return BorderSide(color: colors.blue, width: 2); + return BorderSide(color: colors.blue, width: ZetaSpacing.x0_5); } + if (type.border) { + return BorderSide(color: type == ZetaButtonType.outline ? colors.primary.border : colors.borderDefault); + } + return null; }), elevation: const MaterialStatePropertyAll(0), @@ -260,7 +259,6 @@ class ZetaButton extends StatelessWidget { ); } - // TODO(thelukewalton): Check styles for pressed etc. TextStyle get _textStyle => size == ZetaWidgetSize.small ? ZetaTextStyles.labelMedium : ZetaTextStyles.labelLarge; double get _minConstraints { @@ -285,7 +283,7 @@ class ZetaButton extends StatelessWidget { return ZetaSpacing.x3_5; case ZetaWidgetSize.small: - return 10; + return ZetaSpacing.x2_5; } } @@ -296,7 +294,7 @@ class ZetaButton extends StatelessWidget { ..add(StringProperty('label', label)) ..add(ObjectFlagProperty.has('onPressed', onPressed)) ..add(EnumProperty('type', type)) - ..add(EnumProperty('borderType', borderType)) + ..add(EnumProperty('borderType', borderType)) ..add(EnumProperty('size', size)); } } diff --git a/lib/src/components/buttons/fab.dart b/lib/src/components/buttons/fab.dart index c39c052d..6e383829 100644 --- a/lib/src/components/buttons/fab.dart +++ b/lib/src/components/buttons/fab.dart @@ -4,30 +4,18 @@ import 'package:flutter/rendering.dart'; import '../../../zeta_flutter.dart'; -///Defines the color of the floating action button +/// Color type for [ZetaFAB]. enum ZetaFabType { - ///[primary] + /// Primary color scheme. Defaults to blue. primary, - ///[primarySecond] - primarySecond, + /// Secondary color scheme. Defaults to yellow. + secondary, - ///[inverse] + /// Inverse color scheme. Defaults to dark grey. inverse } -///Defines the shape of the floating action button -enum ZetaFabShape { - ///[circle] - circle, - - ///[rounded] - rounded, - - ///[sharp] - sharp -} - ///Defines the size of the floating action button enum ZetaFabSize { /// [small] 56 pixels @@ -37,49 +25,49 @@ enum ZetaFabSize { large, } -///Zeta Floating Action Button Component +///Zeta Floating Action Button Component. class ZetaFAB extends StatefulWidget { - ///Constructs [ZetaFAB] + ///Constructs [ZetaFAB]. const ZetaFAB({ required this.scrollController, - required this.buttonLabel, - this.buttonType = ZetaFabType.primary, - this.buttonSize = ZetaFabSize.small, - this.buttonShape = ZetaFabShape.circle, - this.buttonIcon = ZetaIcons.add_round, + required this.label, + this.type = ZetaFabType.primary, + this.size = ZetaFabSize.small, + this.shape = ZetaWidgetBorder.full, + this.icon = ZetaIcons.add_round, this.onPressed, - this.customAnimationDuration = const Duration(milliseconds: 300), super.key, }); - ///Defines the color of the button - ///Defaults to [ZetaFabType.primary] - final ZetaFabType buttonType; + /// Defines the color of the button. + /// + /// Defaults to [ZetaFabType.primary] + final ZetaFabType type; - ///The Size of the button - ///Defaults to [ZetaFabSize.small] - final ZetaFabSize buttonSize; + /// The Size of the button. + /// + /// Defaults to [ZetaFabSize.small]. + final ZetaFabSize size; - ///The shape for the button - ///Defaults to [ZetaFabShape.circle] - final ZetaFabShape buttonShape; + /// The shape for the button. + /// + /// Defaults to [ZetaWidgetBorder.full]. + final ZetaWidgetBorder shape; - ///Called when the button is tapped or otherwise activated. + /// Called when the button is tapped or otherwise activated. final VoidCallback? onPressed; - ///The [ZetaFAB] uses this controller to react to scroll change - ///and shrink/expand itself + /// The [ZetaFAB] uses this controller to react to scroll change + /// and shrink/expand itself final ScrollController scrollController; ///The label of the button - final String buttonLabel; - - ///Icon for the button - ///Defaults to [ZetaIcons.add_round] - final IconData buttonIcon; + final String label; - ///Animation Duration - final Duration customAnimationDuration; + /// Icon for the button + /// + /// Defaults to [ZetaIcons.add_round]. + final IconData icon; @override State createState() => _ZetaFABState(); @@ -88,9 +76,9 @@ class ZetaFAB extends StatefulWidget { void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(EnumProperty('buttonType', buttonType)) - ..add(EnumProperty('buttonSize', buttonSize)) - ..add(EnumProperty('buttonShape', buttonShape)) + ..add(EnumProperty('buttonType', type)) + ..add(EnumProperty('buttonSize', size)) + ..add(EnumProperty('buttonShape', shape)) ..add(ObjectFlagProperty.has('onPressed', onPressed)) ..add( DiagnosticsProperty( @@ -98,14 +86,8 @@ class ZetaFAB extends StatefulWidget { scrollController, ), ) - ..add(StringProperty('buttonLabel', buttonLabel)) - ..add(DiagnosticsProperty('buttonIcon', buttonIcon)) - ..add( - DiagnosticsProperty( - 'customAnimationDuration', - customAnimationDuration, - ), - ); + ..add(StringProperty('buttonLabel', label)) + ..add(DiagnosticsProperty('buttonIcon', icon)); } } @@ -134,130 +116,96 @@ class _ZetaFABState extends State { @override Widget build(BuildContext context) { - final theme = Zeta.of(context); - final colors = _FabButtonColors.fromButtonType(widget.buttonType, theme); - final textStyle = _getTextStyle(); - final buttonSize = _getButtonSize(); - final iconSize = _getIconSize(); + final colors = widget.type.colors(context); + final backgroundColor = widget.type == ZetaFabType.inverse ? colors.shade80 : colors.shade60; + return ElevatedButton( onPressed: widget.onPressed, - style: _buttonStyle(colors), - child: AnimatedSwitcher( - duration: widget.customAnimationDuration, - child: _isExpanded ? _buildFABExtended(buttonSize, iconSize, textStyle) : _buildFAB(buttonSize, iconSize), + style: ElevatedButton.styleFrom( + padding: EdgeInsets.zero, + shape: widget.shape.buttonShape(isExpanded: _isExpanded, size: widget.size), + backgroundColor: backgroundColor, + foregroundColor: colors.shade60.onColor, + ).copyWith( + overlayColor: MaterialStateProperty.resolveWith((Set states) { + if (states.contains(MaterialState.hovered)) return colors.hover; + if (states.contains(MaterialState.pressed)) return colors.selected; + return null; + }), + side: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.focused)) { + // TODO(thelukewalton): 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: ZetaSpacing.x0_5); + } + return null; + }, + ), ), - ); - } - - Widget _buildFAB(double buttonSize, double iconSize) { - return SizedBox( - width: buttonSize, - height: buttonSize, - child: Icon(widget.buttonIcon, size: iconSize), - ); - } - - Widget _buildFABExtended( - double buttonSize, - double iconSize, - TextStyle textStyle, - ) { - return Padding( - padding: _getPadding(), - child: SizedBox( - height: buttonSize, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(widget.buttonIcon, size: iconSize), - const SizedBox(width: ZetaSpacing.x2), - Text(widget.buttonLabel, style: textStyle), - ], + child: AnimatedContainer( + duration: const Duration(milliseconds: 300), + child: Padding( + padding: _isExpanded + ? const EdgeInsets.symmetric(horizontal: ZetaSpacing.x3_5, vertical: ZetaSpacing.x3) + : EdgeInsets.all(widget.size.padding), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(widget.icon, size: widget.size.iconSize), + if (_isExpanded) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(widget.label, style: ZetaTextStyles.labelLarge), + ], + ), + ].divide(const SizedBox(width: ZetaSpacing.x2)).toList(), + ), ), ), ); } +} - ButtonStyle _buttonStyle(_FabButtonColors colors) { - return ElevatedButton.styleFrom( - padding: EdgeInsets.zero, - shape: _getButtonShape(), - backgroundColor: colors.backgroundColor, - foregroundColor: colors.foregroundColor, - ).copyWith( - overlayColor: MaterialStateProperty.resolveWith((Set states) { - if (states.contains(MaterialState.pressed)) return colors.actionColor; - return null; - }), - ); +extension on ZetaFabType { + ZetaColorSwatch colors(BuildContext context) { + final zetaColors = Zeta.of(context).colors; + switch (this) { + case ZetaFabType.primary: + return zetaColors.primary; + case ZetaFabType.secondary: + return zetaColors.secondary; + case ZetaFabType.inverse: + return zetaColors.cool; + } } +} - OutlinedBorder _getButtonShape() { - if (widget.buttonShape == ZetaFabShape.circle && !_isExpanded) { +extension on ZetaWidgetBorder { + OutlinedBorder buttonShape({required bool isExpanded, required ZetaFabSize size}) { + if (this == ZetaWidgetBorder.full && !isExpanded) { return const CircleBorder(); } + if (this == ZetaWidgetBorder.sharp) { + return const RoundedRectangleBorder(); + } return RoundedRectangleBorder( - borderRadius: _isExpanded ? _getBorderRadiusExtended() : _getBorderRadius(), + borderRadius: BorderRadius.circular( + isExpanded + ? this == ZetaWidgetBorder.full + ? size == ZetaFabSize.small + ? ZetaSpacing.x7 + : ZetaSpacing.x12 + : ZetaSpacing.x2 + : size == ZetaFabSize.small + ? ZetaSpacing.x2 + : ZetaSpacing.x4, + ), ); } - - BorderRadius _getBorderRadius() => widget.buttonShape == ZetaFabShape.rounded - ? BorderRadius.circular( - widget.buttonSize == ZetaFabSize.small ? ZetaSpacing.x2 : ZetaSpacing.x4, - ) - : BorderRadius.zero; - - BorderRadius _getBorderRadiusExtended() => widget.buttonShape == ZetaFabShape.circle - ? BorderRadius.circular( - widget.buttonSize == ZetaFabSize.small ? ZetaSpacing.x7 : ZetaSpacing.x12, - ) - : widget.buttonShape == ZetaFabShape.rounded - ? BorderRadius.circular(ZetaSpacing.x2) - : BorderRadius.zero; - - TextStyle _getTextStyle() => ZetaTextStyles.labelLarge; - - double _getButtonSize() => widget.buttonSize == ZetaFabSize.small ? ZetaSpacing.x14 : ZetaSpacing.x24; - - double _getIconSize() => widget.buttonSize == ZetaFabSize.small ? ZetaSpacing.x6 : ZetaSpacing.x9; - - EdgeInsets _getPadding() => !_isExpanded - ? EdgeInsets.zero - : widget.buttonShape == ZetaFabShape.circle - ? const EdgeInsets.only(right: 20, left: 20) - : const EdgeInsets.only(right: 18, left: 18); } -///Defines colors for FAB Components -class _FabButtonColors extends ZetaWidgetColor { - const _FabButtonColors({ - required this.actionColor, - required super.backgroundColor, - required super.foregroundColor, - }); - - factory _FabButtonColors.fromButtonType(ZetaFabType buttonType, Zeta theme) { - switch (buttonType) { - case ZetaFabType.primary: - return _FabButtonColors( - backgroundColor: theme.colors.blue.shade60, - foregroundColor: theme.colors.white, - actionColor: theme.colors.blue.shade80, - ); - case ZetaFabType.primarySecond: - return _FabButtonColors( - backgroundColor: theme.colors.yellow.lighten(16), - foregroundColor: theme.colors.black, - actionColor: theme.colors.yellow, - ); - case ZetaFabType.inverse: - return _FabButtonColors( - backgroundColor: theme.colors.iconDefault, - foregroundColor: theme.colors.iconInverse, - actionColor: theme.colors.iconSubtle, - ); - } - } - - final Color actionColor; +extension on ZetaFabSize { + double get iconSize => this == ZetaFabSize.small ? ZetaSpacing.x6 : ZetaSpacing.x9; + double get padding => this == ZetaFabSize.small ? ZetaSpacing.x4 : ZetaSpacing.x7_5; } diff --git a/lib/src/components/checkbox/checkbox.dart b/lib/src/components/checkbox/checkbox.dart index 45b4d41f..22a42060 100644 --- a/lib/src/components/checkbox/checkbox.dart +++ b/lib/src/components/checkbox/checkbox.dart @@ -2,107 +2,210 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; -///Zeta Checkbox -class ZetaCheckbox extends StatelessWidget { +/// Zeta Checkbox. +/// +/// Checkboxes allow users to select one or more items from a set. Checkboxes can turn an option on or off. +class ZetaCheckbox extends FormField { /// Constructs a [ZetaCheckbox]. - const ZetaCheckbox({ - required this.value, - required this.onChanged, - this.borderType = BorderType.sharp, - this.label, - this.checkboxSize = const Size(ZetaSpacing.x5, ZetaSpacing.x5), - this.selectedColor, - this.unselectedColor, - this.unselectedBorderColor, - this.unselectedBorderWidth = 2, - this.disabledColor, - this.isEnabled = true, - this.iconSize = 15.0, + ZetaCheckbox({ super.key, - }) : assert(iconSize > 0, 'Icon size must be greater than 0'); + this.value = false, + this.label, + this.onChanged, + this.rounded = true, + this.useIndeterminate = false, + super.validator, + super.autovalidateMode, + super.restorationId, + }) : super( + initialValue: value, + enabled: onChanged != null, + builder: (field) { + return _Checkbox( + label: label, + onChanged: (changedValue) { + field.didChange(changedValue); + onChanged?.call(changedValue); + }, + rounded: rounded, + useIndeterminate: useIndeterminate, + value: value, + error: !field.isValid, + ); + }, + ); + + /// {@macro zeta-component-rounded} + final bool rounded; + + /// Whether the indeterminate state should be supported. + /// + /// Defaults to false. + final bool useIndeterminate; /// Whether the checkbox is selected, unselected or null (indeterminate) final bool? value; /// Called when the value of the checkbox should change. - final ValueChanged onChanged; - - /// The type of border to display - /// - /// defaults to sharp - final BorderType borderType; + final ValueChanged? onChanged; /// The label displayed next to the checkbox final String? label; - ///Size of the checkbox - final Size checkboxSize; + @override + ZetaCheckboxFormFieldState createState() => ZetaCheckboxFormFieldState(); + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('isChecked', value)) + ..add(StringProperty('label', label)) + ..add(DiagnosticsProperty('useIndeterminate', useIndeterminate)) + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(ObjectFlagProperty?>.has('onChanged', onChanged)); + } +} - /// The color to use when this checkbox is checked. - final Color? selectedColor; +/// [FormFieldState] for [ZetaCheckbox]. +class ZetaCheckboxFormFieldState extends FormFieldState { + @override + ZetaCheckbox get widget => super.widget as ZetaCheckbox; +} - ///Color of the checkbox when it's not selected - final Color? unselectedColor; +class _Checkbox extends StatefulWidget { + const _Checkbox({ + this.value = false, + this.onChanged, + this.label, + this.rounded = true, + this.useIndeterminate = false, + this.error = false, + }); - ///Color of the border when the checkbox not selected - final Color? unselectedBorderColor; + /// Whether the checkbox is selected, unselected or null (indeterminate) + final bool? value; - ///Width of the border when the checkbox is not selected - /// - /// Defaults to 2.5 - final double unselectedBorderWidth; + /// Called when the value of the checkbox should change. + final ValueChanged? onChanged; - ///Size of the icon displayed inside the checkbox - final double iconSize; + /// The label displayed next to the checkbox + final String? label; + + /// {@macro zeta-component-rounded} + final bool rounded; - ///If checkbox is enabled + /// Whether the indeterminate state should be supported. /// - ///defaults to true - final bool isEnabled; + /// Defaults to false. + final bool useIndeterminate; - ///Color of the checkbox when it's disabled - final Color? disabledColor; + final bool error; @override - Widget build(BuildContext context) { - final theme = Zeta.of(context); - final ValueNotifier isFocused = ValueNotifier(false); + State<_Checkbox> createState() => _CheckboxState(); + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + 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)); + } +} + +class _CheckboxState extends State<_Checkbox> { + bool get _enabled => widget.onChanged != null; + + bool? get _value => widget.useIndeterminate ? widget.value : (widget.value ?? false); + + bool? get _updatedValue { + if (widget.useIndeterminate) { + if (widget.value == null) { + return false; + } else if (widget.value!) { + return null; + } else { + return true; + } + } else { + return !_value!; + } + } - return FocusableActionDetector( - onFocusChange: (bool focus) => isFocused.value = focus, - child: GestureDetector( - onTap: _handleOnTap, - child: _buildCheckboxRow(theme, isFocused), + bool _isFocused = false; + bool _isHovered = false; + + @override + Widget build(BuildContext context) { + return Semantics( + checked: _value ?? false, + mixed: widget.useIndeterminate, + enabled: _enabled, + child: MouseRegion( + cursor: _enabled ? SystemMouseCursors.click : SystemMouseCursors.forbidden, + onEnter: (event) => setState(() => _isHovered = true), + onExit: (event) => setState(() => _isHovered = false), + child: _enabled + ? FocusableActionDetector( + onFocusChange: (bool focus) => setState(() => _isFocused = focus), + child: GestureDetector( + onTap: _enabled ? () => widget.onChanged?.call(_updatedValue) : null, + child: _buildContent(context), + ), + ) + : _buildContent(context), ), ); } - void _handleOnTap() { - if (isEnabled) { - onChanged( - value == null - ? true - : value! - ? false - : null, - ); - } - } + Flex _buildContent(BuildContext context) { + final theme = Zeta.of(context); + + final icon = _value != null && !_value! + ? const SizedBox.shrink() + : Icon( + _value != null + ? widget.rounded + ? ZetaIcons.check_round + : ZetaIcons.check_sharp + : widget.rounded + ? ZetaIcons.remove_round + : ZetaIcons.remove_sharp, + color: _enabled ? theme.colors.white : theme.colors.textDisabled, + size: ZetaSpacing.x3_5, + ); - Widget _buildCheckboxRow( - Zeta theme, - ValueNotifier isFocused, - ) { return Flex( direction: Axis.horizontal, mainAxisSize: MainAxisSize.min, children: [ - _buildCheckboxContainer(theme, isFocused), - if (label != null) ...[ + AnimatedContainer( + duration: const Duration(milliseconds: 200), + decoration: BoxDecoration( + boxShadow: [ + if (_isFocused && _enabled) + BoxShadow( + spreadRadius: 2, + blurStyle: BlurStyle.solid, + color: theme.colors.blue.shade50, + ), + ], + color: _getBackground(theme), + border: _enabled ? Border.all(color: _getBorderColor(theme), width: ZetaSpacing.x0_5) : null, + borderRadius: widget.rounded ? ZetaRadius.minimal : ZetaRadius.none, + ), + width: ZetaSpacing.x5, + height: ZetaSpacing.x5, + child: icon, + ), + if (widget.label != null) ...[ Flexible( child: Padding( padding: const EdgeInsets.only(left: ZetaSpacing.s), - child: Text(label!, style: ZetaTextStyles.bodyLarge), + child: Text(widget.label!, style: ZetaTextStyles.bodyLarge), ), ), ], @@ -110,86 +213,31 @@ class ZetaCheckbox extends StatelessWidget { ); } - Widget _buildCheckboxContainer(Zeta theme, ValueNotifier isFocused) { - return ValueListenableBuilder( - valueListenable: isFocused, - builder: (context, focused, child) { - return Container( - decoration: BoxDecoration( - boxShadow: _getBoxShadow(theme, focused), - color: _getCheckboxBackgroundColor(theme), - border: Border.all( - color: _getCheckboxBorderColor(theme), - width: unselectedBorderWidth, - ), - borderRadius: BorderRadius.circular( - borderType == BorderType.rounded ? 2.0 : 0.0, - ), - ), - width: checkboxSize.width, - height: checkboxSize.height, - child: _getCheckboxIcon(theme), - ); - }, - ); - } + Color _getBackground(Zeta theme) { + final ZetaColorSwatch color = widget.error ? theme.colors.error : theme.colors.primary; - List _getBoxShadow(Zeta theme, bool focused) { - if (!focused) return []; - return [ - BoxShadow( - spreadRadius: 3, - color: theme.colors.surfaceSelectedHovered, - ), - ]; - } + if (!_enabled || (_value != null && !_value!)) return theme.colors.surfacePrimary; + if (_isHovered) return color.hover; - Widget _getCheckboxIcon(Zeta theme) { - if (value == null) return const SizedBox.shrink(); - return Icon( - _getIcon(), - color: isEnabled ? theme.colors.white : theme.colors.textDisabled, - size: iconSize, - ); + return color; } - IconData _getIcon() { - final isRounded = borderType == BorderType.rounded; - return value! - ? isRounded - ? ZetaIcons.check_round - : ZetaIcons.check_sharp - : isRounded - ? ZetaIcons.remove_round - : ZetaIcons.remove_sharp; - } + Color _getBorderColor(Zeta theme) { + final ZetaColorSwatch color = widget.error ? theme.colors.error : theme.colors.cool; - Color _getCheckboxBackgroundColor(Zeta theme) { - if (!isEnabled) return disabledColor ?? theme.colors.surfaceDisabled; - if (value == null) return unselectedColor ?? theme.colors.surfaceSecondary; - return selectedColor ?? theme.colors.primary; - } + if (_isHovered) return color.shade90; - Color _getCheckboxBorderColor(Zeta theme) { - if (!isEnabled || value != null) return Colors.transparent; - return unselectedBorderColor ?? theme.colors.borderDefault; + return color; } @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(DiagnosticsProperty('value', value)) - ..add(ObjectFlagProperty>.has('onChanged', onChanged)) - ..add(EnumProperty('borderType', borderType)) - ..add(StringProperty('label', label)) - ..add(DiagnosticsProperty('checkboxSize', checkboxSize)) - ..add(ColorProperty('selectedColor', selectedColor)) - ..add(ColorProperty('unselectedColor', unselectedColor)) - ..add(ColorProperty('unselectedBorderColor', unselectedBorderColor)) - ..add(DoubleProperty('unselectedBorderWidth', unselectedBorderWidth)) - ..add(ColorProperty('disabledColor', disabledColor)) - ..add(DiagnosticsProperty('isEnabled', isEnabled)) - ..add(DoubleProperty('iconSize', iconSize)); + ..add(DiagnosticsProperty('value', widget.value)) + ..add(ObjectFlagProperty>.has('onChanged', widget.onChanged)) + ..add(DiagnosticsProperty('rounded', widget.rounded)) + ..add(StringProperty('label', widget.label)) + ..add(DiagnosticsProperty('useIndeterminate', widget.useIndeterminate)); } } diff --git a/lib/src/components/chip/chip.dart b/lib/src/components/chip/chip.dart deleted file mode 100644 index 05084561..00000000 --- a/lib/src/components/chip/chip.dart +++ /dev/null @@ -1,252 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -import '../../../zeta_flutter.dart'; - -/// The type of [ZetaChip] -enum ZetaChipType { - /// Input Chip - input, - - /// Filter Chip - filter, - - /// Assist Chip - assist, - - /// Status Chip - status, -} - -/// Component [ZetaChip] -class ZetaChip extends StatelessWidget { - /// Constructor for the component [ZetaChip] - const ZetaChip({ - super.key, - required this.type, - required this.label, - this.leading, - this.onDelete, - this.selected = false, - this.rounded = true, - }); - - /// Factory constructor for [ZetaChip] of type `input` - factory ZetaChip.input({ - required String label, - Widget? leading, - VoidCallback? onDelete, - bool rounded = true, - }) { - return ZetaChip( - type: ZetaChipType.input, - label: label, - leading: leading, - onDelete: onDelete, - rounded: rounded, - ); - } - - /// Factory constructor for [ZetaChip] of type `input` - factory ZetaChip.assist({ - required String label, - bool showIcon = false, - Widget? icon, - bool rounded = true, - }) { - final Widget? chipIcon = showIcon ? (icon ?? Icon(rounded ? ZetaIcons.star_round : ZetaIcons.star_sharp)) : null; - return ZetaChip( - type: ZetaChipType.assist, - label: label, - leading: chipIcon, - rounded: rounded, - ); - } - - /// Factory constructor for [ZetaChip] of type `status` - factory ZetaChip.status(String label) { - return ZetaChip( - type: ZetaChipType.status, - label: label, - ); - } - - /// The type of [ZetaChip] - final ZetaChipType type; - - /// The label on the [ZetaChip] - final String label; - - /// The leading icon - final Widget? leading; - - /// The delete action - final VoidCallback? onDelete; - - /// Initial status for the `filter` chiup - final bool selected; - - /// Sets rounded or sharp border. - /// Default is `true`. - final bool rounded; - - @override - Widget build(BuildContext context) { - final colors = Zeta.of(context).colors; - final avatarSize = type == ZetaChipType.input ? ZetaSpacing.x6 : ZetaSpacing.x5; - final bgColor = type == ZetaChipType.status - ? colors.warm.shade30 - : selected - ? colors.textDefault - : colors.surfacePrimary; - - return Chip( - backgroundColor: bgColor, - label: Text(label, textAlign: TextAlign.center), - labelStyle: type == ZetaChipType.status - ? ZetaTextStyles.bodySmall // TODO(thelukewalton): this doesnt match styles on figma. Awaiting design refresh. - : ZetaTextStyles.bodyMedium.apply(color: selected ? colors.textInverse : colors.textDefault), - labelPadding: type == ZetaChipType.status - ? const EdgeInsets.symmetric(horizontal: 10) - : EdgeInsets.fromLTRB( - leading == null ? 14 : 2.5, - 2, - onDelete == null ? 14 : 2.5, - 2, - ), - padding: EdgeInsets.zero, - visualDensity: VisualDensity.compact, - side: BorderSide(color: type == ZetaChipType.status ? bgColor : colors.borderDefault), - shape: RoundedRectangleBorder( - borderRadius: rounded ? BorderRadius.circular(type == ZetaChipType.status ? 6 : 100) : BorderRadius.zero, - ), - clipBehavior: Clip.hardEdge, - avatar: leading == null - ? null - : Container( - width: avatarSize, - height: avatarSize, - decoration: BoxDecoration( - color: bgColor, - borderRadius: BorderRadius.circular(24), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(24), - clipBehavior: Clip.hardEdge, - child: IconTheme( - data: IconThemeData( - color: _getAvatarColor(type, colors), - size: avatarSize, - ), - child: leading!, - ), - ), - ), - deleteIcon: onDelete == null - ? null - : Icon( - Icons.close, - size: 18, - color: colors.iconDefault, - ), - onDeleted: onDelete, - ); - } - - static Color _getAvatarColor(ZetaChipType type, ZetaColors colors) { - switch (type) { - case ZetaChipType.input: - return colors.cool; - case ZetaChipType.filter: - return colors.iconInverse; - case ZetaChipType.assist: - return colors.iconDefault; - case ZetaChipType.status: - return colors.iconDefault; - } - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', type)) - ..add(DiagnosticsProperty('label', label)) - ..add(DiagnosticsProperty('onDelete', onDelete)) - ..add(DiagnosticsProperty('rounded', rounded)) - ..add(DiagnosticsProperty('selected', selected)); - } -} - -/// Component [ZetaFilterChip] -class ZetaFilterChip extends StatefulWidget { - /// Constructor for [ZetaFilterChip] - const ZetaFilterChip({ - super.key, - required this.label, - this.selected = false, - this.onChange, - this.rounded = true, - }); - - /// The label on the [ZetaFilterChip] - final String label; - - /// Initial status - final bool selected; - - /// On change - final void Function({bool value})? onChange; - - /// Sets rounded or sharp border. - /// Default is `true`. - final bool rounded; - - @override - State createState() => _ZetaFilterChipState(); - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('label', label)) - ..add(DiagnosticsProperty('rounded', rounded)) - ..add(DiagnosticsProperty('selected', selected)) - ..add(DiagnosticsProperty('onChange', onChange)); - } -} - -class _ZetaFilterChipState extends State { - late bool _selected; - - @override - void initState() { - super.initState(); - _selected = widget.selected; - } - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: () { - setState(() { - _selected = !_selected; - }); - widget.onChange?.call(value: _selected); - }, - child: _selected - ? ZetaChip( - type: ZetaChipType.filter, - label: widget.label, - leading: const Icon(Icons.check), - selected: _selected, - rounded: widget.rounded, - ) - : ZetaChip( - type: ZetaChipType.filter, - label: widget.label, - rounded: widget.rounded, - ), - ); - } -} diff --git a/lib/src/components/chips/assist_chip.dart b/lib/src/components/chips/assist_chip.dart new file mode 100644 index 00000000..4dc7658d --- /dev/null +++ b/lib/src/components/chips/assist_chip.dart @@ -0,0 +1,14 @@ +import 'chip.dart'; + +/// Zeta Assist Chip. +/// +/// Extends [ZetaChip]. +class ZetaAssistChip extends ZetaChip { + /// Creates a [ZetaAssistChip]. + const ZetaAssistChip({ + super.key, + required super.label, + super.leading, + super.rounded, + }) : super(type: ZetaChipType.assist); +} diff --git a/lib/src/components/chips/chip.dart b/lib/src/components/chips/chip.dart new file mode 100644 index 00000000..26a006c9 --- /dev/null +++ b/lib/src/components/chips/chip.dart @@ -0,0 +1,177 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../../zeta_flutter.dart'; + +export './assist_chip.dart'; +export './filter_chip.dart'; +export './input_chip.dart'; + +/// The type of [ZetaChip] +enum ZetaChipType { + /// Input Chip + input, + + /// Filter Chip + filter, + + /// Assist Chip + assist, +} + +/// Zeta Chip component. +/// +/// This covers the board functionality of [ZetaAssistChip], [ZetaFilterChip] and [ZetaInputChip]. +class ZetaChip extends StatefulWidget { + /// Constructs a [ZetaChip]. + const ZetaChip({ + super.key, + required this.label, + required this.type, + this.leading, + this.rounded = true, + this.trailing, + this.selected, + this.onTap, + }); + + /// Type of [Chip]. + final ZetaChipType type; + + /// The label on the [ZetaChip] + final String label; + + /// Leading component. Typically an [Icon]. + final Widget? leading; + + /// {@macro zeta-component-rounded} + final bool rounded; + + /// Trailing component. Typically an [Icon]. + final Widget? trailing; + + /// Whether the [ZetaFilterChip] is selected. + final bool? selected; + + /// Callback when chip is tapped. + final VoidCallback? onTap; + + @override + State createState() => _ZetaChipState(); + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(EnumProperty('type', type)) + ..add(StringProperty('label', label)) + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(DiagnosticsProperty('selected', selected)) + ..add(ObjectFlagProperty.has('onTap', onTap)); + } +} + +class _ZetaChipState extends State { + bool selected = false; + + Widget? get leading => + widget.leading ?? (selected ? Icon(widget.rounded ? ZetaIcons.check_round : ZetaIcons.check_sharp) : null); + + @override + void initState() { + super.initState(); + selected = widget.selected ?? false; + } + + @override + Widget build(BuildContext context) { + final colors = Zeta.of(context).colors; + final foregroundColor = selected ? colors.textInverse : colors.textDefault; + return FilledButton( + onPressed: () { + if (widget.type == ZetaChipType.filter) { + setState(() => selected = !selected); + } + }, + style: ButtonStyle( + shape: MaterialStateProperty.all( + RoundedRectangleBorder(borderRadius: widget.rounded ? ZetaRadius.full : ZetaRadius.none), + ), + textStyle: MaterialStateProperty.all(ZetaTextStyles.bodyMedium), + backgroundColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.disabled)) { + return colors.surfaceDisabled; + } + if (selected) { + return colors.cool.shade90; + } + if (states.contains(MaterialState.pressed) || states.contains(MaterialState.dragged)) { + return colors.surfaceSelected; + } + + if (states.contains(MaterialState.hovered)) { + return colors.surfaceHovered; + } + + return colors.surfacePrimary; + }), + foregroundColor: MaterialStateProperty.all(foregroundColor), + mouseCursor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.disabled)) { + return SystemMouseCursors.forbidden; + } + if (states.contains(MaterialState.dragged)) { + return SystemMouseCursors.grabbing; + } + return SystemMouseCursors.click; + }), + elevation: MaterialStateProperty.all(0), + side: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.focused)) { + return BorderSide(width: ZetaSpacing.x0_5, color: colors.blue.shade50); + } + return BorderSide(color: colors.borderDefault); + }), + padding: MaterialStateProperty.all( + EdgeInsets.fromLTRB( + widget.leading != null ? ZetaSpacing.x2_5 : ZetaSpacing.x3, + 0, + widget.trailing != null ? ZetaSpacing.x2_5 : ZetaSpacing.x3, + 0, + ), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (leading != null) + IconTheme( + data: IconThemeData( + color: foregroundColor, + size: ZetaSpacing.x5, + ), + child: leading!, + ), + Text(widget.label), + if (widget.trailing != null) + IconTheme( + data: IconThemeData( + color: foregroundColor, + size: ZetaSpacing.x5, + ), + child: widget.trailing!, + ), + ].divide(const SizedBox.square(dimension: ZetaSpacing.x2)).toList(), + ), + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('rounded', widget.rounded)) + ..add(StringProperty('label', widget.label)) + ..add(EnumProperty('type', widget.type)) + ..add(DiagnosticsProperty('selected', widget.selected)); + } +} diff --git a/lib/src/components/chips/filter_chip.dart b/lib/src/components/chips/filter_chip.dart new file mode 100644 index 00000000..bcb08f4e --- /dev/null +++ b/lib/src/components/chips/filter_chip.dart @@ -0,0 +1,14 @@ +import 'chip.dart'; + +/// Zeta Filter Chip. +/// +/// Extends [ZetaChip]. +class ZetaFilterChip extends ZetaChip { + /// Creates a [ZetaInputChip]. + const ZetaFilterChip({ + super.key, + required super.label, + super.rounded, + super.selected, + }) : super(type: ZetaChipType.filter); +} diff --git a/lib/src/components/chips/input_chip.dart b/lib/src/components/chips/input_chip.dart new file mode 100644 index 00000000..896af5b3 --- /dev/null +++ b/lib/src/components/chips/input_chip.dart @@ -0,0 +1,15 @@ +import 'chip.dart'; + +/// Zeta Input Chip. +/// +/// Extends [ZetaChip]. +class ZetaInputChip extends ZetaChip { + /// Creates a [ZetaInputChip]. + const ZetaInputChip({ + super.key, + required super.label, + super.leading, + super.rounded, + super.trailing, + }) : super(type: ZetaChipType.input); +} diff --git a/lib/src/components/password/password_input.dart b/lib/src/components/password/password_input.dart index 32e029ef..59f508a7 100644 --- a/lib/src/components/password/password_input.dart +++ b/lib/src/components/password/password_input.dart @@ -12,7 +12,6 @@ extension on ValueNotifier { class ZetaPasswordInput extends StatefulWidget { ///Constructs [ZetaPasswordInput] const ZetaPasswordInput({ - this.borderType = BorderType.rounded, this.size = ZetaWidgetSize.large, this.validator, this.onChanged, @@ -23,6 +22,7 @@ class ZetaPasswordInput extends StatefulWidget { this.label, this.footerText, this.footerIcon, + this.rounded = false, super.key, }); @@ -47,9 +47,8 @@ class ZetaPasswordInput extends StatefulWidget { /// Optional icon to display beside the footer text. final IconData? footerIcon; - /// Defines the border style of the input field. Can be either [BorderType.rounded] or [BorderType.sharp]. - /// Defaults to [BorderType.rounded]. - final BorderType borderType; + /// {@macro zeta-component-rounded} + final bool rounded; /// Defines the size of the input field. Can be [ZetaWidgetSize.small], [ZetaWidgetSize.medium], or [ZetaWidgetSize.large]. /// Defaults to [ZetaWidgetSize.large]. @@ -78,7 +77,6 @@ class ZetaPasswordInput extends StatefulWidget { ..add(StringProperty('label', label)) ..add(StringProperty('footerText', footerText)) ..add(DiagnosticsProperty('footerIcon', footerIcon)) - ..add(EnumProperty('borderType', borderType)) ..add( ObjectFlagProperty.has( 'validator', @@ -91,7 +89,8 @@ class ZetaPasswordInput extends StatefulWidget { onChanged, ), ) - ..add(EnumProperty('size', size)); + ..add(EnumProperty('size', size)) + ..add(DiagnosticsProperty('rounded', rounded)); } } @@ -108,9 +107,7 @@ class _ZetaPasswordInputState extends State { void _validate() { if (widget.validator != null && widget.controller != null) { - setState( - () => _errorMessage = widget.validator!(widget.controller!.text), - ); + setState(() => _errorMessage = widget.validator!(widget.controller!.text)); } } @@ -124,139 +121,113 @@ class _ZetaPasswordInputState extends State { @override Widget build(BuildContext context) { final theme = Zeta.of(context); - final colors = _ZetaPasswordInputColors(colors: theme.colors); + final defaultBorderColor = _errorMessage != null ? theme.colors.error.border : theme.colors.borderDefault; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (widget.label != null) _buildLabel(), - _buildTextField(context), - if (widget.footerText != null || widget.footerIcon != null || _errorMessage != null) _buildFooter(colors), + if (widget.label != null) + Padding( + padding: const EdgeInsets.symmetric(vertical: ZetaSpacing.x1), + child: Text(widget.label!, style: ZetaTextStyles.bodyMedium), + ), + SizedBox( + height: _inputHeight, + child: ValueListenableBuilder( + valueListenable: _obscureTextNotifier, + builder: (context, obscureValue, child) { + return TextFormField( + controller: widget.controller, + obscureText: obscureValue, + onChanged: widget.onChanged, + style: _textStyle, + decoration: InputDecoration( + contentPadding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.x2), + filled: true, + fillColor: _getBackgroundColor(theme.colors), + enabledBorder: _getBorder(defaultBorderColor), + focusedBorder: _getBorder( + _errorMessage != null ? theme.colors.error.border : theme.colors.primary.border, + width: ZetaSpacing.x0_5, + ), + disabledBorder: _getBorder(theme.colors.borderDefault), + border: _getBorder(defaultBorderColor), + enabled: widget.enabled, + hintText: widget.hintText, + hintStyle: _textStyle, + suffixIcon: ValueListenableBuilder( + valueListenable: _obscureTextNotifier, + builder: (context, value, child) { + return IconButton( + padding: const EdgeInsets.symmetric(vertical: ZetaSpacing.x1), + icon: Icon( + value ? ZetaIcons.visibility_off_sharp : ZetaIcons.visibility_sharp, + size: widget.size == ZetaWidgetSize.small ? ZetaSpacing.x4 : ZetaSpacing.x5, + ), + color: widget.enabled ? theme.colors.iconDefault : theme.colors.iconDisabled, + onPressed: () => _obscureTextNotifier.toggle(), + ); + }, + ), + ), + ); + }, + ), + ), + if (widget.footerText != null || widget.footerIcon != null || _errorMessage != null) + Padding( + padding: const EdgeInsets.only(top: ZetaSpacing.x1), + child: Row( + children: [ + if (_errorMessage != null) ...[ + Icon( + ZetaIcons.error_round, + size: ZetaSpacing.x4, + color: theme.colors.error.border, + ), + const SizedBox(width: ZetaSpacing.x1), + Text( + _errorMessage!, + style: ZetaTextStyles.bodySmall.apply(color: theme.colors.error.border), + ), + ], + if (_errorMessage == null && widget.footerIcon != null) ...[ + Icon( + widget.footerIcon, + size: ZetaSpacing.x4, + color: widget.enabled ? theme.colors.iconDefault : theme.colors.iconDisabled, + ), + const SizedBox(width: ZetaSpacing.x1), + ], + if (_errorMessage == null && widget.footerText != null) ...[ + Text( + widget.footerText!, + style: ZetaTextStyles.bodySmall.apply( + color: widget.enabled ? theme.colors.textSubtle : theme.colors.textDefault, + ), + ), + ], + ], + ), + ), ], ); } - Widget _buildLabel() { - return Padding( - padding: const EdgeInsets.symmetric(vertical: ZetaSpacing.x1), - child: Text(widget.label!, style: ZetaTextStyles.bodyMedium), - ); - } - - Widget _buildTextField(BuildContext context) { - return SizedBox( - height: _getInputHeight(), - child: ValueListenableBuilder( - valueListenable: _obscureTextNotifier, - builder: (context, obscureValue, child) { - return TextFormField( - controller: widget.controller, - obscureText: obscureValue, - onChanged: widget.onChanged, - style: _getTextStyle(), - decoration: _inputDecoration(context), - ); - }, - ), - ); - } - OutlineInputBorder _getBorder(Color color, {double width = 1}) { return OutlineInputBorder( borderSide: BorderSide(color: color, width: width), - borderRadius: BorderRadius.circular( - widget.borderType == BorderType.rounded ? ZetaSpacing.x1 : ZetaSpacing.x0, - ), - ); - } - - InputDecoration _inputDecoration(BuildContext context) { - final theme = Zeta.of(context); - final colors = _ZetaPasswordInputColors(colors: theme.colors); - final defaultBorderColor = _errorMessage != null ? colors.borderErrorColor : colors.borderDefaultColor; - return InputDecoration( - contentPadding: const EdgeInsets.symmetric(horizontal: 8), - filled: true, - fillColor: _getBackgroundColor(colors), - enabledBorder: _getBorder(defaultBorderColor), - focusedBorder: _getBorder( - _errorMessage != null ? colors.borderErrorColor : colors.borderActiveColor, - width: 2, - ), - disabledBorder: _getBorder(colors.borderDisableColor), - border: _getBorder(defaultBorderColor), - enabled: widget.enabled, - hintText: widget.hintText, - hintStyle: _getTextStyle(), - suffixIcon: _buildVisibilityIcon(colors), - ); - } - - Widget _buildFooter(_ZetaPasswordInputColors colors) { - return Padding( - padding: const EdgeInsets.only(top: ZetaSpacing.x1), - child: Row( - children: [ - if (_errorMessage != null) ..._buildError(colors.borderErrorColor), - if (_errorMessage == null && widget.footerIcon != null) ...[ - Icon( - widget.footerIcon, - size: ZetaSpacing.x4, - color: widget.enabled ? colors.hintIconColor : colors.hintIconDisableColor, - ), - const SizedBox(width: ZetaSpacing.x1), - ], - if (_errorMessage == null && widget.footerText != null) ...[ - Text( - widget.footerText!, - style: ZetaTextStyles.bodySmall.apply( - color: widget.enabled ? colors.hintColor : colors.hintDisableColor, - ), - ), - ], - ], - ), - ); - } - - List _buildError(Color color) { - return [ - Icon( - ZetaIcons.error_round, - size: ZetaSpacing.x4, - color: color, - ), - const SizedBox(width: ZetaSpacing.x1), - Text( - _errorMessage!, - style: ZetaTextStyles.bodySmall.apply(color: color), - ), - ]; - } - - Widget _buildVisibilityIcon(_ZetaPasswordInputColors colors) { - return ValueListenableBuilder( - valueListenable: _obscureTextNotifier, - builder: (context, value, child) { - return IconButton( - padding: const EdgeInsets.symmetric(vertical: ZetaSpacing.x1), - icon: Icon( - value ? ZetaIcons.visibility_off_sharp : ZetaIcons.visibility_sharp, - size: _getSuffixIconSize(), - ), - color: widget.enabled ? colors.suffixIconColor : colors.suffixIconDisableColor, - onPressed: () => _obscureTextNotifier.toggle(), - ); - }, + borderRadius: widget.rounded ? ZetaRadius.minimal : ZetaRadius.none, ); } - Color _getBackgroundColor(_ZetaPasswordInputColors colors) { - if (!widget.enabled) return colors.disableColor; - if (_errorMessage != null) return colors.errorColor; - return colors.defaultColor; + Color _getBackgroundColor(ZetaColors zetaColors) { + if (!widget.enabled) return zetaColors.surfaceDisabled; + if (_errorMessage != null) return zetaColors.error.surface; + return zetaColors.surfacePrimary; } - double _getInputHeight() { + double get _inputHeight { switch (widget.size) { case ZetaWidgetSize.small: return ZetaSpacing.x8; @@ -267,45 +238,7 @@ class _ZetaPasswordInputState extends State { } } - TextStyle _getTextStyle() { - if (widget.size == ZetaWidgetSize.small) return ZetaTextStyles.bodyMedium; - return ZetaTextStyles.bodyLarge; - } - - double _getSuffixIconSize() { - if (widget.size == ZetaWidgetSize.small) return ZetaSpacing.x4; - return ZetaSpacing.x5; - } -} - -class _ZetaPasswordInputColors { - const _ZetaPasswordInputColors({required this.colors}); - - final ZetaColors colors; - - Color get defaultColor => colors.surfacePrimary; - - Color get errorColor => colors.red.shade10; - - Color get disableColor => colors.surfaceDisabled; - - Color get borderDefaultColor => colors.borderSubtle; - - Color get borderErrorColor => colors.negative; - - Color get borderActiveColor => colors.primary; - - Color get borderDisableColor => colors.borderSubtle; - - Color get suffixIconColor => colors.iconDefault; - - Color get suffixIconDisableColor => colors.iconDisabled; - - Color get hintColor => colors.textSubtle; - - Color get hintIconColor => colors.iconSubtle; - - Color get hintDisableColor => colors.textDisabled; - - Color get hintIconDisableColor => colors.iconDisabled; + TextStyle get _textStyle => + (widget.size == ZetaWidgetSize.small ? ZetaTextStyles.bodyMedium : ZetaTextStyles.bodyLarge) + .copyWith(height: 1.2); } diff --git a/lib/src/theme/tokens.dart b/lib/src/theme/tokens.dart index 93e534bf..5a31e659 100644 --- a/lib/src/theme/tokens.dart +++ b/lib/src/theme/tokens.dart @@ -9,8 +9,8 @@ class ZetaSpacing { /// Base multiplier used to calculate spacing values. static const double spacingBaseMultiplier = 4; - /// 0dp space. - static const double x0 = spacingBaseMultiplier * 0; + /// 2dp space. + static const double x0_5 = spacingBaseMultiplier * 0.5; /// 4dp space. static const double x1 = spacingBaseMultiplier; @@ -24,6 +24,9 @@ class ZetaSpacing { /// 8dp space. static const double xs = spacingBaseMultiplier * 2; + /// 10dp space. + static const double x2_5 = spacingBaseMultiplier * 2.5; + /// 12dp space. static const double x3 = spacingBaseMultiplier * 3; @@ -51,6 +54,9 @@ class ZetaSpacing { /// 28dp space. static const double x7 = spacingBaseMultiplier * 7; + /// 30dp space. + static const double x7_5 = spacingBaseMultiplier * 7.5; + /// 32dp space. static const double x8 = spacingBaseMultiplier * 8; diff --git a/lib/src/utils/enums.dart b/lib/src/utils/enums.dart index 1979b2c6..787a4f24 100644 --- a/lib/src/utils/enums.dart +++ b/lib/src/utils/enums.dart @@ -1,8 +1,7 @@ -import 'dart:ui'; import '../../zeta_flutter.dart'; -///Border Types -enum BorderType { +/// Border options for [ZetaButton]. +enum ZetaWidgetBorder { /// Sharp border sharp, @@ -13,28 +12,7 @@ enum BorderType { full, } -/// Widget Severity -enum WidgetSeverity { - ///Grey Label - neutral, - - ///Purple Label - info, - - ///Green Label - positive, - - ///Yellow Label - warning, - - ///Red Label - negative, - - ///Custom Label - custom -} - -/// [ZetaWidgetSize] size +/// Size options for [ZetaIndicator], [ZetaWorkcloudIndicator], [ZetaButton], [ZetaPasswordInput]. enum ZetaWidgetSize { /// large large, @@ -46,21 +24,6 @@ enum ZetaWidgetSize { small, } -///Widget Colors -class ZetaWidgetColor { - ///Constructs [ZetaWidgetColor]. - const ZetaWidgetColor({ - required this.backgroundColor, - required this.foregroundColor, - }); - - ///Background Color - final Color backgroundColor; - - ///foregroundColor Color - final Color foregroundColor; -} - /// Status options for [ZetaBadge], [ZetaStatusLabel], [ZetaInPageBanner]. enum ZetaWidgetStatus { /// Information widget; defaults to purple color scheme. diff --git a/lib/src/utils/extensions.dart b/lib/src/utils/extensions.dart index 352b744b..a7347b6f 100644 --- a/lib/src/utils/extensions.dart +++ b/lib/src/utils/extensions.dart @@ -79,3 +79,19 @@ extension ColorSwatches on ZetaWidgetStatus { } } } + +/// Extensions on [String]. +extension StringExtensions on String? { + /// Returns initials from a name. + String get initials { + if (this == null) return ''; + final List nameParts = this!.split(RegExp(r'\W+'))..removeWhere((item) => item.isEmpty); + if (nameParts.isEmpty) return ''; + return (nameParts.length > 1 + ? nameParts[0].substring(0, 1) + nameParts[1].substring(0, 1) + : nameParts[0].length > 1 + ? nameParts[0].substring(0, 2) + : nameParts[0]) + .toUpperCase(); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index bccd6491..eb763dca 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -17,7 +17,7 @@ export 'src/components/bottom sheets/menu_items.dart'; export 'src/components/buttons/button.dart'; export 'src/components/buttons/fab.dart'; export 'src/components/checkbox/checkbox.dart'; -export 'src/components/chip/chip.dart'; +export 'src/components/chips/chip.dart'; export 'src/components/password/password_input.dart'; export 'src/theme/color_extensions.dart'; export 'src/theme/color_scheme.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index a2d399a5..3c073a1e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,13 +16,11 @@ platforms: windows: linux: - environment: sdk: ">=3.0.1 <4.0.0" flutter: ">=3.7.0" dependencies: - cached_network_image: ^3.3.0 flutter: sdk: flutter @@ -47,7 +45,4 @@ flutter: - family: zeta-icons-sharp fonts: - asset: lib/src/assets/fonts/zeta-icons-sharp.ttf - - family: zeta-icons-other - fonts: - - asset: lib/src/assets/fonts/zeta-icons-other.ttf uses-material-design: true diff --git a/zeta-icons-other.json b/zeta-icons-other.json deleted file mode 100644 index eec695e8..00000000 --- a/zeta-icons-other.json +++ /dev/null @@ -1 +0,0 @@ -{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M512 640c106.080 0 192-85.92 192-192s-85.92-192-192-192c-106.080 0-192 85.92-192 192s85.92 192 192 192zM512 736c-128.16 0-384 64.32-384 192v96h768v-96c0-127.68-255.84-192-384-192z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["Group 5"],"colorPermutations":{"25525525518489991":[{}]}},"attrs":[{}],"properties":{"order":771,"id":0,"name":"Avatar","prevSize":32,"code":59648},"setIdx":0,"setId":0,"iconIdx":0}],"height":1024,"metadata":{"name":"icons"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icons","majorVersion":2,"minorVersion":4},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"flutter":true,"showMetadata":false,"showMetrics":false,"showVersion":true,"showSelector":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon","name":"icomoon"},"historySize":50,"showCodes":true,"gridSize":16,"showGrid":false,"showLiga":true}} \ No newline at end of file From 9545b49feb5c5eb0dcb13c878440f89549d19853 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Fri, 2 Feb 2024 14:31:56 +0000 Subject: [PATCH 36/41] chore: Add publish action. (#58) This action should fail when run in internal repository, and only run from ZebraDevs. Whenever a tag is pushed, this should run checks, format and publish package, dependent on admin approval. --- .github/workflows/on-release.yml | 21 + .pubignore | 10 +- docs/components/Color/flutter.md | 102 ---- example/pubspec.lock | 545 ------------------ lib/src/components/banners/system_banner.dart | 3 +- pubspec.yaml | 2 - 6 files changed, 32 insertions(+), 651 deletions(-) delete mode 100644 docs/components/Color/flutter.md delete mode 100644 example/pubspec.lock diff --git a/.github/workflows/on-release.yml b/.github/workflows/on-release.yml index fda831d4..4d6d1bde 100644 --- a/.github/workflows/on-release.yml +++ b/.github/workflows/on-release.yml @@ -5,6 +5,27 @@ on: types: [released] jobs: + check-package: + runs-on: ubuntu-latest + permissions: + id-token: write + environment: pub.dev + steps: + - uses: actions/checkout@v4 + - uses: dart-lang/setup-dart@v1 + - name: Install Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: "3.16.x" + channel: "stable" + - name: Install dependencies + run: flutter pub get + - name: Format code + run: dart format --fix . + - name: Check Publish Warnings + run: dart pub publish --dry-run + - name: Publish + run: dart pub publish --force deploy-website: runs-on: ubuntu-latest steps: diff --git a/.pubignore b/.pubignore index 33e41fc7..f7e9cb5f 100644 --- a/.pubignore +++ b/.pubignore @@ -1 +1,9 @@ -custom_docs/ \ No newline at end of file +custom_docs/ +example/build +example/android +example/ios +example/linux +example/macos +example/web +example/windows +example/widgetbook \ No newline at end of file diff --git a/docs/components/Color/flutter.md b/docs/components/Color/flutter.md deleted file mode 100644 index 86eec97e..00000000 --- a/docs/components/Color/flutter.md +++ /dev/null @@ -1,102 +0,0 @@ -## ZetaColors Usage - -To import ZetaColors into a Dart file: - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; -``` - -### Example - -ZetaColors should be an app-wide parameter, to ensure colors throughout an app stay consistent. As such, it should be created at the highest level of an app, from where it can be distributed. - -```dart -import 'package:zeta_flutter/zeta_flutter.dart'; - -class MyApp extends StatelessWidget{ - const MyApp({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - - /// Build colors object with custom colors. - final ZetaColors colors = ZetaColors( - /// Add custom colors here. - ); - - /// Wrap whole app with [Zeta] to provide theming. - return Zeta( - colors: colors, - builder: (BuildContext context, ThemeData theme, ZetaColors colors) => ZetaColorExample(), - ); - } -} - -class ZetaColorExample extends StatelessWidget{ - const ZetaColorExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - - - final ZetaColors colors = ZetaColors.of(context); - - return Container( - color: colors.red, - ); - } -} - -``` - -### ZetaColors - -ZetaColors provides a full range of colors to be used, with various modifiers to return colors based on function. - -The following colors are provided as `ZetaColorSwatch`: - -- primary -- secondary -- cool (grey) -- warm (grey) -- blue -- red -- green -- orange -- purple -- yellow -- teal -- pink - -When creating a custom ZetaColors object, colors should be provided as a full `ZetaColorSwatch`, unless you want to use the default values, which are described in `ZetaColorBase`. - -ZetaColors has the following modifiers: - -- primary, onPrimary -- secondary, onSecondary -- positive, onPositive, negative, onNegative, warning, onWarning, info, onInfo -- surface, onSurface, surfaceDisabled, surfaceHovered, surfaceSecondary, surfaceTertiary, surfaceSelectedHovered, surfaceSelected -- background, onBackground -- textDefault, textSubtle, textDisabled, textInverse, -- borderDefault, borderSubtle, borderDisabled, borderSelected, -- white, black -- link, linkVisited, -- textLightMode, textDarkMode - -Commonly, `ZetaColors.toColorScheme` should be used to create a color scheme for use with `MaterialApp`. - -### ZetaColorSwatch - -ZetaColorSwatch returns a swatch of colors with shades at 10, 20, 30, 40, 50, 60, 70, 80, 90 and 100 where the higher the value, the darker the color. - -ZetaColorSwatch has the following modifiers: - -- primary -- icon -- border, borderSubtle -- surface -- subtle -- on -- disabled - -ZetaColorSwatch can be generated from a single color, but this is not recommended as results may not look as expected, and will probably not conform to any accessability requirements. diff --git a/example/pubspec.lock b/example/pubspec.lock deleted file mode 100644 index cfd72c73..00000000 --- a/example/pubspec.lock +++ /dev/null @@ -1,545 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - accessibility_tools: - dependency: transitive - description: - name: accessibility_tools - sha256: "0a16adc8dfa3a7ebd38775135d86443011a65d4ecbb438913e4992b5d29135fe" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - async: - dependency: transitive - description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - cached_network_image: - dependency: "direct main" - description: - name: cached_network_image - sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f" - url: "https://pub.dev" - source: hosted - version: "3.3.1" - cached_network_image_platform_interface: - dependency: transitive - description: - name: cached_network_image_platform_interface - sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f" - url: "https://pub.dev" - source: hosted - version: "4.0.0" - cached_network_image_web: - dependency: transitive - description: - name: cached_network_image_web - sha256: "42a835caa27c220d1294311ac409a43361088625a4f23c820b006dd9bffb3316" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - characters: - dependency: transitive - description: - name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - clock: - dependency: transitive - description: - name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" - source: hosted - version: "1.1.1" - collection: - dependency: transitive - description: - name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a - url: "https://pub.dev" - source: hosted - version: "1.18.0" - crypto: - dependency: transitive - description: - name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab - url: "https://pub.dev" - source: hosted - version: "3.0.3" - device_frame: - dependency: transitive - description: - name: device_frame - sha256: afe76182aec178d171953d9b4a50a43c57c7cf3c77d8b09a48bf30c8fa04dd9d - url: "https://pub.dev" - source: hosted - version: "1.1.0" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" - source: hosted - version: "1.3.1" - ffi: - dependency: transitive - description: - name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - file: - dependency: transitive - description: - name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" - url: "https://pub.dev" - source: hosted - version: "7.0.0" - fixnum: - dependency: transitive - description: - name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_cache_manager: - dependency: transitive - description: - name: flutter_cache_manager - sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" - url: "https://pub.dev" - source: hosted - version: "3.3.1" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - freezed_annotation: - dependency: transitive - description: - name: freezed_annotation - sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d - url: "https://pub.dev" - source: hosted - version: "2.4.1" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: "2ccd74480706e0a70a0e0dfa9543dede41bc11d0fe3b146a6ad7b7686f6b4407" - url: "https://pub.dev" - source: hosted - version: "11.1.4" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8 - url: "https://pub.dev" - source: hosted - version: "6.1.0" - http: - dependency: transitive - description: - name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" - source: hosted - version: "4.0.2" - inspector: - dependency: transitive - description: - name: inspector - sha256: "40ba0ac1c819c85139bfec9d1e283804581a8985c91f19d00e93212cf29226b1" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 - url: "https://pub.dev" - source: hosted - version: "4.8.1" - logging: - dependency: transitive - description: - name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" - url: "https://pub.dev" - source: hosted - version: "0.12.16" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" - url: "https://pub.dev" - source: hosted - version: "0.5.0" - meta: - dependency: transitive - description: - name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e - url: "https://pub.dev" - source: hosted - version: "1.10.0" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - octo_image: - dependency: transitive - description: - name: octo_image - sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - path: - dependency: transitive - description: - name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" - url: "https://pub.dev" - source: hosted - version: "1.8.3" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa - url: "https://pub.dev" - source: hosted - version: "2.1.1" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" - url: "https://pub.dev" - source: hosted - version: "2.3.1" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" - url: "https://pub.dev" - source: hosted - version: "2.2.1" - platform: - dependency: transitive - description: - name: platform - sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" - url: "https://pub.dev" - source: hosted - version: "3.1.3" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 - url: "https://pub.dev" - source: hosted - version: "2.1.7" - resizable_widget: - dependency: transitive - description: - name: resizable_widget - sha256: db2919754b93f386b9b3fb15e9f48f6c9d6d41f00a24397629133c99df86606a - url: "https://pub.dev" - source: hosted - version: "1.0.5" - rxdart: - dependency: transitive - description: - name: rxdart - sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" - url: "https://pub.dev" - source: hosted - version: "0.27.7" - shared_preferences: - dependency: "direct main" - description: - name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" - url: "https://pub.dev" - source: hosted - version: "2.2.2" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" - url: "https://pub.dev" - source: hosted - version: "2.2.1" - shared_preferences_foundation: - dependency: transitive - description: - name: shared_preferences_foundation - sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" - url: "https://pub.dev" - source: hosted - version: "2.3.4" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a - url: "https://pub.dev" - source: hosted - version: "2.3.1" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf - url: "https://pub.dev" - source: hosted - version: "2.2.1" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.dev" - source: hosted - version: "1.10.0" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" - sqflite: - dependency: transitive - description: - name: sqflite - sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 - url: "https://pub.dev" - source: hosted - version: "2.3.2" - sqflite_common: - dependency: transitive - description: - name: sqflite_common - sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" - url: "https://pub.dev" - source: hosted - version: "2.5.3" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" - url: "https://pub.dev" - source: hosted - version: "1.11.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.dev" - source: hosted - version: "2.1.2" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - synchronized: - dependency: transitive - description: - name: synchronized - sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" - url: "https://pub.dev" - source: hosted - version: "3.1.0+1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - test_api: - dependency: transitive - description: - name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" - url: "https://pub.dev" - source: hosted - version: "0.6.1" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://pub.dev" - source: hosted - version: "1.3.2" - uuid: - dependency: transitive - description: - name: uuid - sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 - url: "https://pub.dev" - source: hosted - version: "4.3.3" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - web: - dependency: transitive - description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 - url: "https://pub.dev" - source: hosted - version: "0.3.0" - widgetbook: - dependency: "direct dev" - description: - name: widgetbook - sha256: bdbfdc517923218394f11ad4e004a7e3d45672047e9d87f52833ac294366232d - url: "https://pub.dev" - source: hosted - version: "3.7.0" - win32: - dependency: transitive - description: - name: win32 - sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 - url: "https://pub.dev" - source: hosted - version: "5.1.1" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" - url: "https://pub.dev" - source: hosted - version: "1.0.3" - zeta_flutter: - dependency: "direct main" - description: - path: ".." - relative: true - source: path - version: "0.1.1+23" -sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" - flutter: ">=3.10.0" diff --git a/lib/src/components/banners/system_banner.dart b/lib/src/components/banners/system_banner.dart index 6648e49e..deccf34a 100644 --- a/lib/src/components/banners/system_banner.dart +++ b/lib/src/components/banners/system_banner.dart @@ -40,7 +40,8 @@ class ZetaSystemBanner extends MaterialBanner { final foregroundColor = backgroundColor.onColor; if (context.mounted) { // ignore: invalid_use_of_visible_for_testing_member - if (Platform.isAndroid && SystemChrome.latestStyle?.statusBarColor != backgroundColor) { + final statusBarColor = SystemChrome.latestStyle?.statusBarColor; + if (Platform.isAndroid && statusBarColor != backgroundColor) { SystemChrome.setSystemUIOverlayStyle( SystemUiOverlayStyle( statusBarColor: backgroundColor, diff --git a/pubspec.yaml b/pubspec.yaml index 3c073a1e..b9fae23e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,8 +25,6 @@ dependencies: sdk: flutter dev_dependencies: - flutter_test: - sdk: flutter zds_analysis: ^1.0.0 flutter: From 9d69548b53ddc711afd67721b996cf3890dbbe9a Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Wed, 6 Sep 2023 17:03:19 +0100 Subject: [PATCH 37/41] chore: Tidy, reorganise and prepare repo docs: update changelog and documentation feat(type): Add xSmall and conform to latest figma designs. --- .pubignore | 2 +- CHANGELOG.md | 403 +++++++++------------ README.md | 2 + example/lib/pages/theme/color_example.dart | 26 +- example/macos/Podfile.lock | 4 +- 5 files changed, 194 insertions(+), 243 deletions(-) diff --git a/.pubignore b/.pubignore index f7e9cb5f..6df95062 100644 --- a/.pubignore +++ b/.pubignore @@ -6,4 +6,4 @@ example/linux example/macos example/web example/windows -example/widgetbook \ No newline at end of file +example/widgetbook diff --git a/CHANGELOG.md b/CHANGELOG.md index d41fc235..1a205901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,52 +1,63 @@ ## [0.1.1+23] - 2024-01-19 + ### :wrench: Chores -- [`ed1210d`](https://github.com/zebratechnologies/zeta-flutter/commit/ed1210d6cbc173aef8b1adf0d20ee91d3e87f2c3) - Update Widgetbook to correct functionality *(PR [#52](https://github.com/zebratechnologies/zeta-flutter/pull/52) by [@thelukewalton](https://github.com/thelukewalton))* -- [`c627d7a`](https://github.com/zebratechnologies/zeta-flutter/commit/c627d7ab19d3f33e30c406441702ff6134557f14) - Tidy up example app *(PR [#53](https://github.com/zebratechnologies/zeta-flutter/pull/53) by [@thelukewalton](https://github.com/thelukewalton))* +- [`ed1210d`](https://github.com/zebratechnologies/zeta-flutter/commit/ed1210d6cbc173aef8b1adf0d20ee91d3e87f2c3) - Update Widgetbook to correct functionality _(PR [#52](https://github.com/zebratechnologies/zeta-flutter/pull/52) by [@thelukewalton](https://github.com/thelukewalton))_ +- [`c627d7a`](https://github.com/zebratechnologies/zeta-flutter/commit/c627d7ab19d3f33e30c406441702ff6134557f14) - Tidy up example app _(PR [#53](https://github.com/zebratechnologies/zeta-flutter/pull/53) by [@thelukewalton](https://github.com/thelukewalton))_ ## [0.1.1+22] - 2024-01-19 + ### :boom: BREAKING CHANGES -- due to [`7b543ac`](https://github.com/zebratechnologies/zeta-flutter/commit/7b543ac7b92dc53a866af4de313c36b5728e912e) - Remove legacy code *(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))*: + +- due to [`7b543ac`](https://github.com/zebratechnologies/zeta-flutter/commit/7b543ac7b92dc53a866af4de313c36b5728e912e) - Remove legacy code _(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))_: Removed ZetaGrid and ZetaSpacing components, renamed widget padding extensions https://jira.zebra.com/browse/UX-910 Remove ZetaGrid, ZetaSpacing and ZetaText widgets as these are no longer part of the library. Functionality is retained in some cases (text - styles, padding extensions) but widgets themselves are removed. - --------- + styles, padding extensions) but widgets themselves are removed. + *** ### :sparkles: New Features -- [`7b543ac`](https://github.com/zebratechnologies/zeta-flutter/commit/7b543ac7b92dc53a866af4de313c36b5728e912e) - Remove legacy code *(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))* + +- [`7b543ac`](https://github.com/zebratechnologies/zeta-flutter/commit/7b543ac7b92dc53a866af4de313c36b5728e912e) - Remove legacy code _(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))_ ### :wrench: Chores -- [`ccbdeb9`](https://github.com/zebratechnologies/zeta-flutter/commit/ccbdeb93b6995eb3a3ff66562d957bc7e2470432) - Update Widgetbook to correct functionality *(PR [#52](https://github.com/zebratechnologies/zeta-flutter/pull/52) by [@thelukewalton](https://github.com/thelukewalton))* +- [`ccbdeb9`](https://github.com/zebratechnologies/zeta-flutter/commit/ccbdeb93b6995eb3a3ff66562d957bc7e2470432) - Update Widgetbook to correct functionality _(PR [#52](https://github.com/zebratechnologies/zeta-flutter/pull/52) by [@thelukewalton](https://github.com/thelukewalton))_ ## [0.1.1+21] - 2024-01-18 + ### :sparkles: New Features -- [`6ae1269`](https://github.com/zebratechnologies/zeta-flutter/commit/6ae1269422180bbf2ecbfd05814969bfcbb725f1) - Update text styles to match latest designs *(PR [#50](https://github.com/zebratechnologies/zeta-flutter/pull/50) by [@thelukewalton](https://github.com/thelukewalton))* -- [`977d7e6`](https://github.com/zebratechnologies/zeta-flutter/commit/977d7e6f7cb0c2b67085ab40f5cf1d410e5680c8) - Remove legacy code *(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))* +- [`6ae1269`](https://github.com/zebratechnologies/zeta-flutter/commit/6ae1269422180bbf2ecbfd05814969bfcbb725f1) - Update text styles to match latest designs _(PR [#50](https://github.com/zebratechnologies/zeta-flutter/pull/50) by [@thelukewalton](https://github.com/thelukewalton))_ +- [`977d7e6`](https://github.com/zebratechnologies/zeta-flutter/commit/977d7e6f7cb0c2b67085ab40f5cf1d410e5680c8) - Remove legacy code _(PR [#51](https://github.com/zebratechnologies/zeta-flutter/pull/51) by [@thelukewalton](https://github.com/thelukewalton))_ ## [0.1.1+20] - 2024-01-17 + ### :sparkles: New Features -- [`35d1d7e`](https://github.com/zebratechnologies/zeta-flutter/commit/35d1d7eed509d4b89593c17e2a48a4a2c79a6ce4) - Update text styles to match latest designs *(PR [#50](https://github.com/zebratechnologies/zeta-flutter/pull/50) by [@thelukewalton](https://github.com/thelukewalton))* + +- [`35d1d7e`](https://github.com/zebratechnologies/zeta-flutter/commit/35d1d7eed509d4b89593c17e2a48a4a2c79a6ce4) - Update text styles to match latest designs _(PR [#50](https://github.com/zebratechnologies/zeta-flutter/pull/50) by [@thelukewalton](https://github.com/thelukewalton))_ ### :wrench: Chores -- [`6787220`](https://github.com/zebratechnologies/zeta-flutter/commit/67872203f0dc96de02e6945f0ac4409f95872262) - Organize ilb/ to match web *(PR [#49](https://github.com/zebratechnologies/zeta-flutter/pull/49) by [@thelukewalton](https://github.com/thelukewalton))* +- [`6787220`](https://github.com/zebratechnologies/zeta-flutter/commit/67872203f0dc96de02e6945f0ac4409f95872262) - Organize ilb/ to match web _(PR [#49](https://github.com/zebratechnologies/zeta-flutter/pull/49) by [@thelukewalton](https://github.com/thelukewalton))_ ## [0.1.1+19] - 2024-01-17 + ### :wrench: Chores -- [`d1c0125`](https://github.com/zebratechnologies/zeta-flutter/commit/d1c012523e16ebbf3f38c7028598660cfc7b7ea9) - Organize ilb/ to match web *(PR [#49](https://github.com/zebratechnologies/zeta-flutter/pull/49) by [@thelukewalton](https://github.com/thelukewalton))* + +- [`d1c0125`](https://github.com/zebratechnologies/zeta-flutter/commit/d1c012523e16ebbf3f38c7028598660cfc7b7ea9) - Organize ilb/ to match web _(PR [#49](https://github.com/zebratechnologies/zeta-flutter/pull/49) by [@thelukewalton](https://github.com/thelukewalton))_ ### :flying_saucer: Other Changes + - [`aff41a3`](https://github.com/zebratechnologies/zeta-flutter/commit/aff41a372a2e3ba7eef06e1d69dc3e57b423c3dd) - chore(deps): bump tj-actions/changed-files from 35 to 41 in /.github/workflows ([#48](https://github.com/zebratechnologies/zeta-flutter/pull/48)) Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 35 to 41. +
    Release notes

    Sourced from You can trigger Dependabot actions by commenting on this PR: + - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits -that have been made to it + that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after -your CI passes on it + your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge -and block automerging + and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating -it. You can achieve the same result by closing it manually + it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all -of the ignore conditions of the specified dependency + of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop -Dependabot creating any more for this major version (unless you reopen -the PR or upgrade to it yourself) + Dependabot creating any more for this major version (unless you reopen + the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop -Dependabot creating any more for this minor version (unless you reopen -the PR or upgrade to it yourself) + Dependabot creating any more for this minor version (unless you reopen + the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop -Dependabot creating any more for this dependency (unless you reopen the -PR or upgrade to it yourself) -You can disable automated security fix PRs for this repo from the -[Security Alerts -page](https://github.com/zebratechnologies/zeta-flutter/network/alerts). + Dependabot creating any more for this dependency (unless you reopen the + PR or upgrade to it yourself) + You can disable automated security fix PRs for this repo from the + [Security Alerts + page](https://github.com/zebratechnologies/zeta-flutter/network/alerts).

    Signed-off-by: dependabot[bot] -Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@dependabot[bot]](https://github.com/apps/dependabot))* - +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> _(commit by [@dependabot[bot]](https://github.com/apps/dependabot))_ ## [0.1.1+18] - 2024-01-10 + ### :flying_saucer: Other Changes + - [`caea7bd`](https://github.com/zebratechnologies/zeta-flutter/commit/caea7bdc061149db64344526bd16cd5232a219c2) - chore(deps): bump tj-actions/changed-files from 35 to 41 in /.github/workflows ([#48](https://github.com/zebratechnologies/zeta-flutter/pull/48)) Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 35 to 41. +
    Release notes

    Sourced from


    - [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tj-actions/changed-files&package-manager=github_actions&previous-version=35&new-version=41)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) @@ -569,8 +582,8 @@ Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. -[//]: # (dependabot-automerge-start) -[//]: # (dependabot-automerge-end) +[//]: # "dependabot-automerge-start" +[//]: # "dependabot-automerge-end" --- @@ -579,113 +592,125 @@ alter it yourself. You can also trigger a rebase manually by commenting
    You can trigger Dependabot actions by commenting on this PR: + - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits -that have been made to it + that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after -your CI passes on it + your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge -and block automerging + and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating -it. You can achieve the same result by closing it manually + it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all -of the ignore conditions of the specified dependency + of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop -Dependabot creating any more for this major version (unless you reopen -the PR or upgrade to it yourself) + Dependabot creating any more for this major version (unless you reopen + the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop -Dependabot creating any more for this minor version (unless you reopen -the PR or upgrade to it yourself) + Dependabot creating any more for this minor version (unless you reopen + the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop -Dependabot creating any more for this dependency (unless you reopen the -PR or upgrade to it yourself) -You can disable automated security fix PRs for this repo from the -[Security Alerts -page](https://github.com/zebratechnologies/zeta-flutter/network/alerts). + Dependabot creating any more for this dependency (unless you reopen the + PR or upgrade to it yourself) + You can disable automated security fix PRs for this repo from the + [Security Alerts + page](https://github.com/zebratechnologies/zeta-flutter/network/alerts). Signed-off-by: dependabot[bot] -Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> *(commit by [@dependabot[bot]](https://github.com/apps/dependabot))* - +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> _(commit by [@dependabot[bot]](https://github.com/apps/dependabot))_ ## [0.1.1+16] - 2024-01-02 + ### :flying_saucer: Other Changes + - [`225a059`](https://github.com/zebratechnologies/zeta-flutter/commit/225a059aa191f595db4982960c854c2e94c5bdc4) - create bottom sheet ([#45](https://github.com/zebratechnologies/zeta-flutter/pull/45)) Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ + - [`656ca24`](https://github.com/zebratechnologies/zeta-flutter/commit/656ca2470112a171064f0d2d7477bf087a4f98bd) - Password input ([#47](https://github.com/zebratechnologies/zeta-flutter/pull/47)) Co-authored-by: github-actions -Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - +Co-authored-by: Atanas Yordanov _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.1+15] - 2024-01-02 + ### :flying_saucer: Other Changes + - [`36b9808`](https://github.com/zebratechnologies/zeta-flutter/commit/36b980896602320114c845b68a99a1c4c2e03ecb) - Page banner ([#40](https://github.com/zebratechnologies/zeta-flutter/pull/40)) -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ + - [`03f2ed7`](https://github.com/zebratechnologies/zeta-flutter/commit/03f2ed7fb7f34dd995cb850f67582b76a2132111) - create bottom sheet ([#45](https://github.com/zebratechnologies/zeta-flutter/pull/45)) Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.1+14] - 2023-12-21 + ### :flying_saucer: Other Changes + - [`be7cf58`](https://github.com/zebratechnologies/zeta-flutter/commit/be7cf587995ef4a51c57fc497d91abfccf82c65b) - component floating action button ([#41](https://github.com/zebratechnologies/zeta-flutter/pull/41)) -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* -- [`a5d7181`](https://github.com/zebratechnologies/zeta-flutter/commit/a5d71816ff9d6aa9426cda38ee9d6f1116a36496) - Page banner ([#40](https://github.com/zebratechnologies/zeta-flutter/pull/40)) +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`a5d7181`](https://github.com/zebratechnologies/zeta-flutter/commit/a5d71816ff9d6aa9426cda38ee9d6f1116a36496) - Page banner ([#40](https://github.com/zebratechnologies/zeta-flutter/pull/40)) +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.1+13] - 2023-12-21 + ### :flying_saucer: Other Changes + - [`51caca7`](https://github.com/zebratechnologies/zeta-flutter/commit/51caca71fce57681cabeb82e979499da9a16f4c1) - Menu Items - horizontal & vertical ([#44](https://github.com/zebratechnologies/zeta-flutter/pull/44)) * Menu Items - horizontal & vertical * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* -- [`8fe8750`](https://github.com/zebratechnologies/zeta-flutter/commit/8fe87502764834cdbdcc7580bddaa5def36ae518) - component floating action button ([#41](https://github.com/zebratechnologies/zeta-flutter/pull/41)) +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +- [`8fe8750`](https://github.com/zebratechnologies/zeta-flutter/commit/8fe87502764834cdbdcc7580bddaa5def36ae518) - component floating action button ([#41](https://github.com/zebratechnologies/zeta-flutter/pull/41)) +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.1+12] - 2023-12-20 + ### :flying_saucer: Other Changes + - [`dcafe1f`](https://github.com/zebratechnologies/zeta-flutter/commit/dcafe1f2f0436adf75e9cb36e0c4dd1bb8015def) - fix sizings and replace icons with zeta icons ([#43](https://github.com/zebratechnologies/zeta-flutter/pull/43)) * fix sizings and replace icons with zeta icons * [automated commit] lint format and import sort ---------- +--- + +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`231fa4b`](https://github.com/zebratechnologies/zeta-flutter/commit/231fa4b860d4ecbb551ba7ec65b783d26fed43a0) - Menu Items - horizontal & vertical ([#44](https://github.com/zebratechnologies/zeta-flutter/pull/44)) * Menu Items - horizontal & vertical * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.1+11] - 2023-12-19 + ### :flying_saucer: Other Changes + - [`c506b81`](https://github.com/zebratechnologies/zeta-flutter/commit/c506b81c0f00b23192ddef4e484dabf8a0f36890) - Component accordion ([#39](https://github.com/zebratechnologies/zeta-flutter/pull/39)) * first draft of the ZetaAccordion @@ -710,35 +735,37 @@ Co-authored-by: github-actions *(commit by [@atanasy * [automated commit] lint format and import sort ---------- +--- Co-authored-by: github-actions Co-authored-by: Atanas Yordanov -* add comments and more examples +- add comments and more examples -* pubspec +- pubspec -* [automated commit] lint format and import sort +- [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ + - [`10a075e`](https://github.com/zebratechnologies/zeta-flutter/commit/10a075ed9dc7aac6021ccc08fde574f520b2fc9e) - fix sizings and replace icons with zeta icons ([#43](https://github.com/zebratechnologies/zeta-flutter/pull/43)) * fix sizings and replace icons with zeta icons * [automated commit] lint format and import sort ---------- - -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +--- +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.1+10] - 2023-12-19 + ### :flying_saucer: Other Changes + - [`c79686a`](https://github.com/zebratechnologies/zeta-flutter/commit/c79686a8221a029280332e144da3fdb6eca0ead8) - Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) * initial @@ -753,10 +780,11 @@ Co-authored-by: github-actions *(commit by [@genovev * [automated commit] lint format and import sort ---------- +--- Co-authored-by: github-actions -Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +Co-authored-by: Atanas Yordanov _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ + - [`df9eb66`](https://github.com/zebratechnologies/zeta-flutter/commit/df9eb66803c2f005099aa67a9394e520626401d3) - Component accordion ([#39](https://github.com/zebratechnologies/zeta-flutter/pull/39)) * first draft of the ZetaAccordion @@ -781,36 +809,38 @@ Co-authored-by: Atanas Yordanov *(commit by [@ * [automated commit] lint format and import sort ---------- +--- Co-authored-by: github-actions Co-authored-by: Atanas Yordanov -* add comments and more examples +- add comments and more examples -* pubspec +- pubspec -* [automated commit] lint format and import sort +- [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.1+9] - 2023-12-18 + ### :flying_saucer: Other Changes + - [`541ec63`](https://github.com/zebratechnologies/zeta-flutter/commit/541ec633f31f117b685671a33342e57c89823434) - force Material 3 ([#38](https://github.com/zebratechnologies/zeta-flutter/pull/38)) * force Material 3 * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ + - [`0be43ac`](https://github.com/zebratechnologies/zeta-flutter/commit/0be43acce7c8f3b69a778f95420f542f92e725cf) - Tag component ([#37](https://github.com/zebratechnologies/zeta-flutter/pull/37)) * initial @@ -825,14 +855,15 @@ Co-authored-by: github-actions *(commit by [@atanasy * [automated commit] lint format and import sort ---------- +--- Co-authored-by: github-actions -Co-authored-by: Atanas Yordanov *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - +Co-authored-by: Atanas Yordanov _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.1+8] - 2023-12-18 + ### :flying_saucer: Other Changes + - [`4ca71f3`](https://github.com/zebratechnologies/zeta-flutter/commit/4ca71f3f83535e55c3af36961a5332fced0ecdbf) - Button component ([#36](https://github.com/zebratechnologies/zeta-flutter/pull/36)) * initial @@ -853,23 +884,25 @@ Co-authored-by: Atanas Yordanov *(commit by [@ * [automated commit] lint format and import sort ---------- +--- + +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`ba9062b`](https://github.com/zebratechnologies/zeta-flutter/commit/ba9062bb2268310a8c22d5230227c04afa178166) - force Material 3 ([#38](https://github.com/zebratechnologies/zeta-flutter/pull/38)) * force Material 3 * [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.1+7] - 2023-12-18 + ### :flying_saucer: Other Changes + - [`ac2b269`](https://github.com/zebratechnologies/zeta-flutter/commit/ac2b269c5806d2af310a063231abc1e412aea1a1) - fix the border of the indicator component ([#31](https://github.com/zebratechnologies/zeta-flutter/pull/31)) * fix the border of the component @@ -892,10 +925,11 @@ Co-authored-by: github-actions *(commit by [@atanasy * stick to Material 2 for now ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ + - [`cb330c7`](https://github.com/zebratechnologies/zeta-flutter/commit/cb330c7c1952ca2493b5d6c9272e2ade1050f53b) - Button component ([#36](https://github.com/zebratechnologies/zeta-flutter/pull/36)) * initial @@ -916,13 +950,14 @@ Co-authored-by: github-actions *(commit by [@atanasy * [automated commit] lint format and import sort ---------- - -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +--- +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.1+6] - 2023-12-18 + ### :flying_saucer: Other Changes + - [`354040c`](https://github.com/zebratechnologies/zeta-flutter/commit/354040c91731f53f9186ce0cbce341706dc30b3a) - Workcloud indicators ([#34](https://github.com/zebratechnologies/zeta-flutter/pull/34)) * initial @@ -949,9 +984,10 @@ Co-authored-by: github-actions *(commit by [@genovev * [automated commit] lint format and import sort ---------- +--- + +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`88080ad`](https://github.com/zebratechnologies/zeta-flutter/commit/88080ada71811b47fe20f73dfba23c52e5223d38) - fix the border of the indicator component ([#31](https://github.com/zebratechnologies/zeta-flutter/pull/31)) * fix the border of the component @@ -974,14 +1010,15 @@ Co-authored-by: github-actions *(commit by [@genovev * stick to Material 2 for now ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.1+5] - 2023-12-18 + ### :flying_saucer: Other Changes + - [`1268c92`](https://github.com/zebratechnologies/zeta-flutter/commit/1268c92c7e0057cd166c40bc9ccd53ccf80c2fef) - App bar ([#35](https://github.com/zebratechnologies/zeta-flutter/pull/35)) * create ZetaAppBar in four variants with example screens @@ -994,10 +1031,11 @@ Co-authored-by: github-actions *(commit by [@atanasy * titleIcon should be of type Icon instead of Widget ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ + - [`077d161`](https://github.com/zebratechnologies/zeta-flutter/commit/077d16138d5d3f579fbc2bfcba3048b1c5d28afc) - Workcloud indicators ([#34](https://github.com/zebratechnologies/zeta-flutter/pull/34)) * initial @@ -1024,13 +1062,14 @@ Co-authored-by: github-actions *(commit by [@atanasy * [automated commit] lint format and import sort ---------- - -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* +--- +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ ## [0.1.1+4] - 2023-12-15 + ### :flying_saucer: Other Changes + - [`8f621dc`](https://github.com/zebratechnologies/zeta-flutter/commit/8f621dc82bd58ace9c994057420cdb1f41a74200) - Component ZetaAvatar ([#32](https://github.com/zebratechnologies/zeta-flutter/pull/32)) * add empty avatar example page; upgrade packages @@ -1085,21 +1124,22 @@ Co-authored-by: github-actions *(commit by [@genovev * [automated commit] lint format and import sort ---------- +--- Co-authored-by: github-actions -* [automated commit] lint format and import sort +- [automated commit] lint format and import sort -* replace photo with image +- replace photo with image -* [automated commit] lint format and import sort +- [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions -Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* +Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ + - [`350adec`](https://github.com/zebratechnologies/zeta-flutter/commit/350adecf4b0498afc6a476a653d2223a7cb74e0f) - App bar ([#35](https://github.com/zebratechnologies/zeta-flutter/pull/35)) * create ZetaAppBar in four variants with example screens @@ -1112,14 +1152,15 @@ Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.gi * titleIcon should be of type Icon instead of Widget ---------- +--- Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.1+3] - 2023-12-15 + ### :flying_saucer: Other Changes + - [`5f0a33e`](https://github.com/zebratechnologies/zeta-flutter/commit/5f0a33e8e3b92de83d83170f267e6cd3f5fca068) - Merge from zebradevs ([#27](https://github.com/zebratechnologies/zeta-flutter/pull/27)) * Merge from zebradevs @@ -1128,9 +1169,10 @@ Co-authored-by: github-actions *(commit by [@atanasy * [automated commit] lint format and import sort ---------- +--- + +Co-authored-by: github-actions _(commit by [@thelukewalton](https://github.com/thelukewalton))_ -Co-authored-by: github-actions *(commit by [@thelukewalton](https://github.com/thelukewalton))* - [`b20aef1`](https://github.com/zebratechnologies/zeta-flutter/commit/b20aef109944e6cfc02db9b0041e7a6009c9e52e) - Component ZetaAvatar ([#32](https://github.com/zebratechnologies/zeta-flutter/pull/32)) * add empty avatar example page; upgrade packages @@ -1185,34 +1227,36 @@ Co-authored-by: github-actions *(commit by [@theluke * [automated commit] lint format and import sort ---------- +--- Co-authored-by: github-actions -* [automated commit] lint format and import sort +- [automated commit] lint format and import sort -* replace photo with image +- replace photo with image -* [automated commit] lint format and import sort +- [automated commit] lint format and import sort ---------- +--- Co-authored-by: Atanas Yordanov Co-authored-by: github-actions -Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> *(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))* - +Co-authored-by: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ ## [0.1.1+2] - 2023-12-13 + ### :flying_saucer: Other Changes + - [`063386f`](https://github.com/zebratechnologies/zeta-flutter/commit/063386f83490bf3bfb6d26fc6a95dd445006d656) - some sizings were not exactly as shown in Figma ([#33](https://github.com/zebratechnologies/zeta-flutter/pull/33)) * . * [automated commit] lint format and import sort ---------- +--- + +Co-authored-by: github-actions _(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))_ -Co-authored-by: github-actions *(commit by [@genovevageorgieva](https://github.com/genovevageorgieva))* - [`1c8ca4c`](https://github.com/zebratechnologies/zeta-flutter/commit/1c8ca4c4b5dbd8378710a18765303a6d37472cf0) - Merge from zebradevs ([#27](https://github.com/zebratechnologies/zeta-flutter/pull/27)) * Merge from zebradevs @@ -1221,10 +1265,9 @@ Co-authored-by: github-actions *(commit by [@genovev * [automated commit] lint format and import sort ---------- - -Co-authored-by: github-actions *(commit by [@thelukewalton](https://github.com/thelukewalton))* +--- +Co-authored-by: github-actions _(commit by [@thelukewalton](https://github.com/thelukewalton))_ ## [0.1.1+1] - 2023-12-01 @@ -1537,7 +1580,6 @@ Co-authored-by: github-actions _(commit by [@atanasy - [`0ee6171`](https://github.com/zebratechnologies/zeta-flutter/commit/0ee6171e779c6db9995308aa35f2f598b9db372c) - Cleanup dart warnings; fix text scale ([#23](https://github.com/zebratechnologies/zeta-flutter/pull/23)) * fix endtemplate in comments; upgrade flutter packages - <<<<<<< HEAD * remove unnecessary text scaling @@ -1547,97 +1589,6 @@ Co-authored-by: github-actions _(commit by [@atanasy Co-authored-by: Atanas Yordanov Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ -======= - -> > > > > > > 38a5a89 (Merge from zebradevs) - -- remove unnecessary text scaling - -- [automated commit] lint format and import sort - ---- - -Co-authored-by: Atanas Yordanov -Co-authored-by: github-actions _(commit by [@atanasyordanov21](https://github.com/atanasyordanov21))_ - -## [0.1.0+1] - 2023-11-28 - -- chore: Tidy, reorganise and prepare repo - -docs: update changelog and documentation - -feat(type): Add xSmall and conform to latest figma designs. - -- "Refactored the ZetaColors class for better customization - -The ZetaColors class was heavily refactored for better customization of variables such as brightness, contrast, color swatches, and additional color attributes. Several fields were made final for the overall class safety. This change improves color control on different themes for the application." - -- "Updated the ZetaColor and Theme setup to use InheritedWidget - -The ZetaDefaults class was updated to Zeta inheriting from InheritedWidget. This change allows easy access to the Zeta theme settings (contrast, theme mode, theme data, color set) from anywhere in the widget tree. The ZetaAppBuilder function was updated to take in ThemeData and ThemeMode. The ZetaProvider was added to provide Zeta theming and contrast data down the widget tree. The code for the color and typography examples was adjusted to use the new Zeta context extension, instead of using Theme.of(context) to get colorScheme. This change was crucial to simplify the process of adapting the application visuals to different themes." - -- "Improve theme management functionality in Zeta - -Removed code concerning getting a color's RGB hex code from 'color_extensions.dart', as it was seldom used. Updated 'zeta_flutter.dart' to unhide ZetaColorGetters. Adaptations in 'zeta.dart' included switching mediaBrightness to \_mediaBrightness for internal use and adding methods for accurate determination of color set and brightness settings based on the theme mode. Also, ZetaProvider was updated for 'system' theme mode support. example/lib/main.dart and example/lib/widgets.dart were updated to support these changes, including UI updates for seamless theme switching." - -- "Add theme update function and extend ZetaColorGetters - -Implemented a method in 'zeta.dart' to support updating the current theme data dynamically. Extended 'color_scheme.dart' by introducing \_ZetaColorProperties and updating ZetaColorGetters. These changes increase flexibility for theme management and provide a structured and accessible way to get Zeta colors through the theme context." - -- Remove theme_extensions.dart and move contents to colors.dart - -Theme extensions were deleted and its contents were moved to colors.dart to consolidate all color-related codes in one file for easier navigation and editing. Additional enhancements include optimizing color assignments and making ZetaColors immutable for more robust color management. - -- Refactor code for color theme and add theme switcher - -Refactored codebase to improve the color theme handling: relocated theme related methods to colors.dart from theme_extensions.dart for consolidated color theme data. Optimized color assignments by leveraging the 'copyWith' method, allowing more efficient color management. Introduced the immutability of ZetaColors to enhance robustness. Bumped version in pubspec.yaml to 0.0.1+13 due to these changes. Renamed theme.dart to theme_data.dart for more semantic file naming. Added 'identifier' to the ZetaThemeData for easier theme identification. -The visible application change is an added ThemeSwitcher in the example app, offering a UI to switch between different predefined themes. - -- Add ZetaThemeService and theme switcher in example app - -Implemented ZetaThemeService as an abstract class, providing structure for loading and saving themes within the app. Removed an obsolete comment within the contrast.dart and made necessary imports in zeta.dart. Asynchronous theme loading is added during app startup and saving is done upon theme updates. Also, for user-interaction, an exclusive ThemeSwitcher widget is added in the example app allowing users to select between available themes. This improves user experience, and optimizes theme handling and application performance. - -- Refactor color swatch generation to utilize zeta - -Refactored color swatch generation in color_example.dart to use Zeta instead of directly using the Theme. Now the brightness for ZetaColorSwatch is being pulled from zeta object rather than theme. This ensures consistency across different parts of the application where Zeta is used. Also changed theme.colorScheme.surface to colors.surfacePrimary for better readability, and alignment with use of zeta object. - -- Add icon colors to color scheme - -Extended the color scheme in colors.dart to include default, subtle, disabled, and inverse icon colors. These were added to ensure consistent icon colors across the application and support dark mode by allowing inverted color swatches. - -- Refactor theme switch settings and add new features - -Renamed 'theme_switch.dart' to 'theme_color_switch.dart' and added two new files 'theme_contrast_switch.dart' and 'theme_mode_switch.dart' in order to separate the theme settings logically into distinct features - Theme Color Switch, Theme Contrast Switch and Theme Mode Switch respectively. Also, the theme application feature has been refactored within 'widgets.dart' to use the newly created theme features instead of the old theme switch. This enhances modularity and the user's ability to switch theme settings easily. - -- Update method naming for consistent architecture in text.dart - -Changed the method name 'withColor' to 'themeWithColor' in text.dart for consistency with other part of the architecture and for better readability. This change supports the shift towards a consistently designed application architecture and helps developers easily decipher the role of the method in the code. - -- Update color scheme mapping and library version in colors.dart and pubspec.lock - -Refined the color mapping in ZetaColorScheme in colors.dart by replacing effectiveSurfaceTertiary with textDefault, enhancing the clarity of backdrop's color role. Concurrently, version of multiple dependencies in pubspec.lock are updated to benefit from recent fixes and improvements in those libraries. - -- Change `Color` to `ZetaColorSwatch` in theme files - -Adjusted the class references in colors.dart from `Color` to `ZetaColorSwatch` to provide a more consistent color swatch across the app. The swatch allows for more flexibility in using color variations. Adjustments were also made in color_scheme.dart and color_swatch.dart to include better explanatory messages and use standard dart documentation format. Changes in custom_docs/components/Color/flutter.md were made to align with these updates. - -- Enhance contrast and color handling in theme files - -Removed 'flutter.md' as it is no longer required due to improvements made in contrast and color handling. For better accessibility support, 'contrast.dart' was refactored for better contrast handling and 'color_extensions.dart' now includes a mechanism to generate color swatch based on contrast ratio. Also, 'zeta.dart' was updated to adapt to the system's brightness providing better user experience. Overall, these adjustments aim to enhance accessibility and user experience, apart from simplifying the codebase. - -- Add LICENSE-3RD-PARTY for third-party libraries - -Introduced license details for third-party libraries used in the project. MIT license applies to 'tinycolor' and SIL Open Font License applies to 'IBMPlexSans'. This ensures proper acknowledgement and licensure compliance for used third-party resources. - -- Set up with ZDS Analysis - -## [0.0.1+12] - 2023-09-06 - -### :wrench: Chores - -- [`6a2834e`](https://github.com/zebratechnologies/zeta-flutter/commit/6a2834e762c238d3927d83a239490250b1687b64) - Tidy, reorganise and prepare repo _(commit by [@thelukewalton](https://github.com/thelukewalton))_ - -### :flying_saucer: Other Changes - [`f91e8ef`](https://github.com/zebratechnologies/zeta-flutter/commit/f91e8ef85c0a1670227d66bd441513bc33e6242c) - Feature/color ([#21](https://github.com/zebratechnologies/zeta-flutter/pull/21)) @@ -1758,4 +1709,4 @@ Introduced license details for third-party libraries used in the project. MIT li [0.1.1+20]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+19...0.1.1+20 [0.1.1+21]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+20...0.1.1+21 [0.1.1+22]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+21...0.1.1+22 -[0.1.1+23]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+22...0.1.1+23 \ No newline at end of file +[0.1.1+23]: https://github.com/zebratechnologies/zeta-flutter/compare/0.1.1+22...0.1.1+23 diff --git a/README.md b/README.md index eb8c75bd..7437d3b5 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Zeta is the new, formal, standardized Zebra Design System based off the successe To install `zeta_flutter`, follow the instructions [here](https://pub.dev/packages/zeta_flutter/install). ## Usage + Zeta offers flexibility in theming through its `ZetaProvider` widget. Here's a breakdown of its features: ### Setting the Initial Theme Mode @@ -83,6 +84,7 @@ To tie everything together, use the `ZetaProvider` constructor. The `builder` ar ``` With these configurations, Zeta makes it easy to achieve consistent theming throughout your Flutter application. + ## Viewing the components To view examples of all the components in the library, you can run the example app in this repo or go to [Zeta](https://zeta-ds.web.app/) diff --git a/example/lib/pages/theme/color_example.dart b/example/lib/pages/theme/color_example.dart index 46698389..9d962a9e 100644 --- a/example/lib/pages/theme/color_example.dart +++ b/example/lib/pages/theme/color_example.dart @@ -158,21 +158,19 @@ class _ColorExampleState extends State { 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)), - ], - ), + child: Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ + DefaultTextStyle( + style: ZetaTextStyles.bodyMedium + .copyWith(color: calculateTextColor(value.value[e] ?? Colors.white)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Text('${value.key.toLowerCase().replaceAll(' ', '')}-$e'), + Text(value.value[e].toString().replaceAll('Color(0xff', '#').substring(0, 7)), + ], ), - ], - ), + ), + ]), ), ), ), diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index 151506c3..4556329c 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -28,8 +28,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 - shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 + path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c + shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 From 10e7bb7f67a16c7f1d6e5b3a1f95e9c1539c6137 Mon Sep 17 00:00:00 2001 From: Prashant Sawant <75819349+ps9310@users.noreply.github.com> Date: Thu, 9 Nov 2023 08:38:12 -0500 Subject: [PATCH 38/41] System theme support (#1) * chore: Tidy, reorganise and prepare repo docs: update changelog and documentation feat(type): Add xSmall and conform to latest figma designs. * "Refactored the ZetaColors class for better customization The ZetaColors class was heavily refactored for better customization of variables such as brightness, contrast, color swatches, and additional color attributes. Several fields were made final for the overall class safety. This change improves color control on different themes for the application." * "Updated the ZetaColor and Theme setup to use InheritedWidget The ZetaDefaults class was updated to Zeta inheriting from InheritedWidget. This change allows easy access to the Zeta theme settings (contrast, theme mode, theme data, color set) from anywhere in the widget tree. The ZetaAppBuilder function was updated to take in ThemeData and ThemeMode. The ZetaProvider was added to provide Zeta theming and contrast data down the widget tree. The code for the color and typography examples was adjusted to use the new Zeta context extension, instead of using Theme.of(context) to get colorScheme. This change was crucial to simplify the process of adapting the application visuals to different themes." * "Improve theme management functionality in Zeta Removed code concerning getting a color's RGB hex code from 'color_extensions.dart', as it was seldom used. Updated 'zeta_flutter.dart' to unhide ZetaColorGetters. Adaptations in 'zeta.dart' included switching mediaBrightness to _mediaBrightness for internal use and adding methods for accurate determination of color set and brightness settings based on the theme mode. Also, ZetaProvider was updated for 'system' theme mode support. example/lib/main.dart and example/lib/widgets.dart were updated to support these changes, including UI updates for seamless theme switching." * "Add theme update function and extend ZetaColorGetters Implemented a method in 'zeta.dart' to support updating the current theme data dynamically. Extended 'color_scheme.dart' by introducing _ZetaColorProperties and updating ZetaColorGetters. These changes increase flexibility for theme management and provide a structured and accessible way to get Zeta colors through the theme context." * Remove theme_extensions.dart and move contents to colors.dart Theme extensions were deleted and its contents were moved to colors.dart to consolidate all color-related codes in one file for easier navigation and editing. Additional enhancements include optimizing color assignments and making ZetaColors immutable for more robust color management. * Refactor code for color theme and add theme switcher Refactored codebase to improve the color theme handling: relocated theme related methods to colors.dart from theme_extensions.dart for consolidated color theme data. Optimized color assignments by leveraging the 'copyWith' method, allowing more efficient color management. Introduced the immutability of ZetaColors to enhance robustness. Bumped version in pubspec.yaml to 0.0.1+13 due to these changes. Renamed theme.dart to theme_data.dart for more semantic file naming. Added 'identifier' to the ZetaThemeData for easier theme identification. The visible application change is an added ThemeSwitcher in the example app, offering a UI to switch between different predefined themes. * Add ZetaThemeService and theme switcher in example app Implemented ZetaThemeService as an abstract class, providing structure for loading and saving themes within the app. Removed an obsolete comment within the contrast.dart and made necessary imports in zeta.dart. Asynchronous theme loading is added during app startup and saving is done upon theme updates. Also, for user-interaction, an exclusive ThemeSwitcher widget is added in the example app allowing users to select between available themes. This improves user experience, and optimizes theme handling and application performance. * Refactor color swatch generation to utilize zeta Refactored color swatch generation in color_example.dart to use Zeta instead of directly using the Theme. Now the brightness for ZetaColorSwatch is being pulled from zeta object rather than theme. This ensures consistency across different parts of the application where Zeta is used. Also changed theme.colorScheme.surface to colors.surfacePrimary for better readability, and alignment with use of zeta object. * Add icon colors to color scheme Extended the color scheme in colors.dart to include default, subtle, disabled, and inverse icon colors. These were added to ensure consistent icon colors across the application and support dark mode by allowing inverted color swatches. * Refactor theme switch settings and add new features Renamed 'theme_switch.dart' to 'theme_color_switch.dart' and added two new files 'theme_contrast_switch.dart' and 'theme_mode_switch.dart' in order to separate the theme settings logically into distinct features - Theme Color Switch, Theme Contrast Switch and Theme Mode Switch respectively. Also, the theme application feature has been refactored within 'widgets.dart' to use the newly created theme features instead of the old theme switch. This enhances modularity and the user's ability to switch theme settings easily. * Update method naming for consistent architecture in text.dart Changed the method name 'withColor' to 'themeWithColor' in text.dart for consistency with other part of the architecture and for better readability. This change supports the shift towards a consistently designed application architecture and helps developers easily decipher the role of the method in the code. * Update color scheme mapping and library version in colors.dart and pubspec.lock Refined the color mapping in ZetaColorScheme in colors.dart by replacing effectiveSurfaceTertiary with textDefault, enhancing the clarity of backdrop's color role. Concurrently, version of multiple dependencies in pubspec.lock are updated to benefit from recent fixes and improvements in those libraries. * Change `Color` to `ZetaColorSwatch` in theme files Adjusted the class references in colors.dart from `Color` to `ZetaColorSwatch` to provide a more consistent color swatch across the app. The swatch allows for more flexibility in using color variations. Adjustments were also made in color_scheme.dart and color_swatch.dart to include better explanatory messages and use standard dart documentation format. Changes in custom_docs/components/Color/flutter.md were made to align with these updates. * Enhance contrast and color handling in theme files Removed 'flutter.md' as it is no longer required due to improvements made in contrast and color handling. For better accessibility support, 'contrast.dart' was refactored for better contrast handling and 'color_extensions.dart' now includes a mechanism to generate color swatch based on contrast ratio. Also, 'zeta.dart' was updated to adapt to the system's brightness providing better user experience. Overall, these adjustments aim to enhance accessibility and user experience, apart from simplifying the codebase. * Add LICENSE-3RD-PARTY for third-party libraries Introduced license details for third-party libraries used in the project. MIT license applies to 'tinycolor' and SIL Open Font License applies to 'IBMPlexSans'. This ensures proper acknowledgement and licensure compliance for used third-party resources. --------- Co-authored-by: Luke Walton --- example/lib/home.dart | 1 - example/lib/pages/theme_color_switch.dart | 69 +++++++++++++++++++ example/lib/pages/theme_constrast_switch.dart | 56 +++++++++++++++ example/lib/pages/theme_mode_switch.dart | 60 ++++++++++++++++ 4 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 example/lib/pages/theme_color_switch.dart create mode 100644 example/lib/pages/theme_constrast_switch.dart create mode 100644 example/lib/pages/theme_mode_switch.dart diff --git a/example/lib/home.dart b/example/lib/home.dart index 659ca5f7..aaafbe7b 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -18,7 +18,6 @@ class Component { final String name; final WidgetBuilder pageBuilder; final List children; - Component(this.name, this.pageBuilder, [this.children = const []]); } diff --git a/example/lib/pages/theme_color_switch.dart b/example/lib/pages/theme_color_switch.dart new file mode 100644 index 00000000..a2ca12fc --- /dev/null +++ b/example/lib/pages/theme_color_switch.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ZetaThemeColorSwitch extends StatelessWidget { + ZetaThemeColorSwitch({super.key}); + + late final _themes = { + "default": ZetaThemeData(), + "teal": ZetaThemeData( + identifier: 'teal', + primary: ZetaColorBase.teal, + ), + "yellow": ZetaThemeData( + identifier: 'yellow', + primary: ZetaColorBase.yellow, + ), + "red": ZetaThemeData( + identifier: 'red', + primary: ZetaColorBase.red, + ), + "purple": ZetaThemeData( + identifier: 'purple', + primary: ZetaColorBase.purple, + ), + }; + + @override + Widget build(BuildContext context) { + var zeta = Zeta.of(context); + + ZetaColors primary(ZetaThemeData data) { + if (zeta.brightness == Brightness.light) { + return data.colorsLight; + } else { + return data.colorsDark; + } + } + + return DropdownButtonHideUnderline( + child: DropdownButton( + value: zeta.themeData.identifier, + elevation: 0, + isDense: true, + alignment: Alignment.center, + icon: SizedBox(width: 8), + dropdownColor: zeta.colors.borderDisabled, + items: _themes.entries.map((e) { + var zetaColors = primary(_themes[e.key]!); + var color = zetaColors.primary; + return DropdownMenuItem( + value: e.value.identifier, + alignment: Alignment.center, + child: CircleAvatar( + backgroundColor: color.surface, + foregroundColor: color, + child: Icon(Icons.color_lens, color: color), + ), + ); + }).toList(), + onChanged: (value) { + final theme = _themes[value]; + if (theme != null) { + ZetaProvider.of(context).updateThemeData(theme); + } + }, + ), + ); + } +} diff --git a/example/lib/pages/theme_constrast_switch.dart b/example/lib/pages/theme_constrast_switch.dart new file mode 100644 index 00000000..9d36c28f --- /dev/null +++ b/example/lib/pages/theme_constrast_switch.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ZetaThemeContrastSwitch extends StatelessWidget { + ZetaThemeContrastSwitch({super.key}); + + late final _themes = [ + ZetaContrast.aa, + ZetaContrast.aaa, + ]; + + @override + Widget build(BuildContext context) { + var zeta = Zeta.of(context); + + ZetaColors zetaColors(ZetaContrast contrast) { + if (zeta.brightness == Brightness.light) { + return zeta.themeData.apply(contrast: contrast).colorsLight; + } else { + return zeta.themeData.apply(contrast: contrast).colorsDark; + } + } + + return DropdownButtonHideUnderline( + child: DropdownButton( + value: zeta.contrast, + elevation: 0, + isDense: true, + alignment: Alignment.center, + icon: SizedBox(width: 8), + dropdownColor: zeta.colors.borderDisabled, + items: _themes.map((e) { + final colors = zetaColors(e); + return DropdownMenuItem( + value: e, + alignment: Alignment.center, + child: CircleAvatar( + backgroundColor: colors.primary.surface, + foregroundColor: colors.primary, + child: ZetaText.bodyMedium( + e == ZetaContrast.aa ? 'AA' : 'AAA', + textColor: colors.primary, + fontWeight: FontWeight.w700, + ), + ), + ); + }).toList(), + onChanged: (value) { + if (value != null) { + ZetaProvider.of(context).updateContrast(value); + } + }, + ), + ); + } +} diff --git a/example/lib/pages/theme_mode_switch.dart b/example/lib/pages/theme_mode_switch.dart new file mode 100644 index 00000000..392d7e12 --- /dev/null +++ b/example/lib/pages/theme_mode_switch.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ZetaThemeModeSwitch extends StatelessWidget { + ZetaThemeModeSwitch({super.key}); + + late final _themes = [ + ThemeMode.system, + ThemeMode.light, + ThemeMode.dark, + ]; + + @override + Widget build(BuildContext context) { + var zeta = Zeta.of(context); + + ZetaColors zetaColors(ThemeMode mode) { + if ((mode == ThemeMode.system && MediaQuery.of(context).platformBrightness == Brightness.light) || + mode == ThemeMode.light) { + return zeta.themeData.colorsLight; + } else { + return zeta.themeData.colorsDark; + } + } + + return DropdownButtonHideUnderline( + child: DropdownButton( + value: zeta.themeMode, + elevation: 0, + isDense: true, + alignment: Alignment.center, + icon: SizedBox(width: 8), + dropdownColor: zeta.colors.borderDisabled, + items: _themes.map((e) { + final colors = zetaColors(e); + return DropdownMenuItem( + value: e, + alignment: Alignment.center, + child: CircleAvatar( + backgroundColor: colors.primary.surface, + foregroundColor: colors.primary, + child: Icon( + e == ThemeMode.system + ? Icons.system_security_update_good + : e == ThemeMode.light + ? Icons.light_mode + : Icons.dark_mode, + color: colors.primary), + ), + ); + }).toList(), + onChanged: (value) { + if (value != null) { + ZetaProvider.of(context).updateThemeMode(value); + } + }, + ), + ); + } +} From dec383da049a520ef622679f6292ed05f3a1c279 Mon Sep 17 00:00:00 2001 From: Prashant Sawant <75819349+ps9310@users.noreply.github.com> Date: Fri, 1 Dec 2023 13:03:37 -0500 Subject: [PATCH 39/41] Refactor theme declaration and introduce theme service (#8) In theme_color_switch.dart, restructured the declaration of themes into a global constant 'appThemes', freeing it from a class field in ZetaThemeColorSwitch. This increases application efficiency and adheres to the DRY (Don't Repeat Yourself) principle. A new file 'theme_service.dart' was also added, serving as an abstract class for loading and saving theme data. Various typos in 'colors.dart' and 'zeta.dart' were fixed to ensure correct execution. Theme data loading and saving operations in 'main.dart' were also updated to use this new service. --- example/lib/pages/theme_color_switch.dart | 46 +++++++++---------- .../Flutter/GeneratedPluginRegistrant.swift | 16 ------- lib/src/theme/colors.dart | 2 +- 3 files changed, 24 insertions(+), 40 deletions(-) delete mode 100644 example/macos/Flutter/GeneratedPluginRegistrant.swift diff --git a/example/lib/pages/theme_color_switch.dart b/example/lib/pages/theme_color_switch.dart index a2ca12fc..98ebbeec 100644 --- a/example/lib/pages/theme_color_switch.dart +++ b/example/lib/pages/theme_color_switch.dart @@ -1,29 +1,29 @@ import 'package:flutter/material.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; +late final appThemes = { + "default": ZetaThemeData(), + "teal": ZetaThemeData( + identifier: 'teal', + primary: ZetaColorBase.teal, + ), + "yellow": ZetaThemeData( + identifier: 'yellow', + primary: ZetaColorBase.yellow, + ), + "red": ZetaThemeData( + identifier: 'red', + primary: ZetaColorBase.red, + ), + "purple": ZetaThemeData( + identifier: 'purple', + primary: ZetaColorBase.purple, + ), +}; + class ZetaThemeColorSwitch extends StatelessWidget { ZetaThemeColorSwitch({super.key}); - late final _themes = { - "default": ZetaThemeData(), - "teal": ZetaThemeData( - identifier: 'teal', - primary: ZetaColorBase.teal, - ), - "yellow": ZetaThemeData( - identifier: 'yellow', - primary: ZetaColorBase.yellow, - ), - "red": ZetaThemeData( - identifier: 'red', - primary: ZetaColorBase.red, - ), - "purple": ZetaThemeData( - identifier: 'purple', - primary: ZetaColorBase.purple, - ), - }; - @override Widget build(BuildContext context) { var zeta = Zeta.of(context); @@ -44,8 +44,8 @@ class ZetaThemeColorSwitch extends StatelessWidget { alignment: Alignment.center, icon: SizedBox(width: 8), dropdownColor: zeta.colors.borderDisabled, - items: _themes.entries.map((e) { - var zetaColors = primary(_themes[e.key]!); + items: appThemes.entries.map((e) { + var zetaColors = primary(appThemes[e.key]!); var color = zetaColors.primary; return DropdownMenuItem( value: e.value.identifier, @@ -58,7 +58,7 @@ class ZetaThemeColorSwitch extends StatelessWidget { ); }).toList(), onChanged: (value) { - final theme = _themes[value]; + final theme = appThemes[value]; if (theme != null) { ZetaProvider.of(context).updateThemeData(theme); } diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift deleted file mode 100644 index eefcc6d7..00000000 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - -import path_provider_foundation -import shared_preferences_foundation -import sqflite - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) - SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) -} diff --git a/lib/src/theme/colors.dart b/lib/src/theme/colors.dart index bdab7cb4..1e54689e 100644 --- a/lib/src/theme/colors.dart +++ b/lib/src/theme/colors.dart @@ -252,11 +252,11 @@ class ZetaColors { /// {@macro zeta-color-dark} Color get textInverse => cool.shade20; + /// {@template zeta-color-dark} /// Default icon color. /// /// Defaults to `ZetaColors.cool.90`. /// - /// {@template zeta-color-dark} /// Color swatches are inverted if [ZetaColors.brightness] is Dark. /// {@endtemplate} Color get iconDefault => textDefault; From 6d9ad765129d8921b45713e23bfbbad27a293412 Mon Sep 17 00:00:00 2001 From: Genoveva Georgieva <151932404+genovevageorgieva@users.noreply.github.com> Date: Tue, 5 Dec 2023 13:01:25 +0200 Subject: [PATCH 40/41] Checkbox (#9) * checkbox * remove comment * widgetbook * widgetbook --- example/lib/pages/theme/color_example.dart | 18 ++--- example/lib/pages/theme_color_switch.dart | 69 ------------------ example/lib/pages/theme_constrast_switch.dart | 56 -------------- example/lib/pages/theme_mode_switch.dart | 60 --------------- .../Flutter/GeneratedPluginRegistrant.swift | 16 ++++ example/widgetbook/widgetbook.dart | 5 +- lib/src/assets/fonts/zeta-icons-other.ttf | Bin 1088 -> 0 bytes .../bottom sheets/bottom_sheet.dart | 5 +- lib/src/components/buttons/fab.dart | 2 +- 9 files changed, 28 insertions(+), 203 deletions(-) delete mode 100644 example/lib/pages/theme_color_switch.dart delete mode 100644 example/lib/pages/theme_constrast_switch.dart delete mode 100644 example/lib/pages/theme_mode_switch.dart create mode 100644 example/macos/Flutter/GeneratedPluginRegistrant.swift delete mode 100644 lib/src/assets/fonts/zeta-icons-other.ttf diff --git a/example/lib/pages/theme/color_example.dart b/example/lib/pages/theme/color_example.dart index 9d962a9e..da441b7c 100644 --- a/example/lib/pages/theme/color_example.dart +++ b/example/lib/pages/theme/color_example.dart @@ -123,15 +123,15 @@ class _ColorExampleState extends State { }; final Map primaries = { - 'primaryColor': colors.primary, - 'secondaryColor': colors.secondary, + 'primaryColor': colors.primary.text, + 'secondaryColor': colors.secondary.text, }; final Map alerts = { - 'positive': colors.positive, - 'negative': colors.negative, - 'warning': colors.warning, - 'info': colors.info, + 'positive': colors.positive.text, + 'negative': colors.negative.text, + 'warning': colors.warning.text, + 'info': colors.info.text, }; return ExampleScaffold( @@ -291,12 +291,6 @@ class MyRow extends StatelessWidget { } } -extension StringExtension on Color { - String get toHexString { - return toString().substring(10, 16).toUpperCase(); - } -} - Color calculateTextColor(Color background) { return ThemeData.estimateBrightnessForColor(background) == Brightness.light ? Colors.black : Colors.white; } diff --git a/example/lib/pages/theme_color_switch.dart b/example/lib/pages/theme_color_switch.dart deleted file mode 100644 index 98ebbeec..00000000 --- a/example/lib/pages/theme_color_switch.dart +++ /dev/null @@ -1,69 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -late final appThemes = { - "default": ZetaThemeData(), - "teal": ZetaThemeData( - identifier: 'teal', - primary: ZetaColorBase.teal, - ), - "yellow": ZetaThemeData( - identifier: 'yellow', - primary: ZetaColorBase.yellow, - ), - "red": ZetaThemeData( - identifier: 'red', - primary: ZetaColorBase.red, - ), - "purple": ZetaThemeData( - identifier: 'purple', - primary: ZetaColorBase.purple, - ), -}; - -class ZetaThemeColorSwitch extends StatelessWidget { - ZetaThemeColorSwitch({super.key}); - - @override - Widget build(BuildContext context) { - var zeta = Zeta.of(context); - - ZetaColors primary(ZetaThemeData data) { - if (zeta.brightness == Brightness.light) { - return data.colorsLight; - } else { - return data.colorsDark; - } - } - - return DropdownButtonHideUnderline( - child: DropdownButton( - value: zeta.themeData.identifier, - elevation: 0, - isDense: true, - alignment: Alignment.center, - icon: SizedBox(width: 8), - dropdownColor: zeta.colors.borderDisabled, - items: appThemes.entries.map((e) { - var zetaColors = primary(appThemes[e.key]!); - var color = zetaColors.primary; - return DropdownMenuItem( - value: e.value.identifier, - alignment: Alignment.center, - child: CircleAvatar( - backgroundColor: color.surface, - foregroundColor: color, - child: Icon(Icons.color_lens, color: color), - ), - ); - }).toList(), - onChanged: (value) { - final theme = appThemes[value]; - if (theme != null) { - ZetaProvider.of(context).updateThemeData(theme); - } - }, - ), - ); - } -} diff --git a/example/lib/pages/theme_constrast_switch.dart b/example/lib/pages/theme_constrast_switch.dart deleted file mode 100644 index 9d36c28f..00000000 --- a/example/lib/pages/theme_constrast_switch.dart +++ /dev/null @@ -1,56 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -class ZetaThemeContrastSwitch extends StatelessWidget { - ZetaThemeContrastSwitch({super.key}); - - late final _themes = [ - ZetaContrast.aa, - ZetaContrast.aaa, - ]; - - @override - Widget build(BuildContext context) { - var zeta = Zeta.of(context); - - ZetaColors zetaColors(ZetaContrast contrast) { - if (zeta.brightness == Brightness.light) { - return zeta.themeData.apply(contrast: contrast).colorsLight; - } else { - return zeta.themeData.apply(contrast: contrast).colorsDark; - } - } - - return DropdownButtonHideUnderline( - child: DropdownButton( - value: zeta.contrast, - elevation: 0, - isDense: true, - alignment: Alignment.center, - icon: SizedBox(width: 8), - dropdownColor: zeta.colors.borderDisabled, - items: _themes.map((e) { - final colors = zetaColors(e); - return DropdownMenuItem( - value: e, - alignment: Alignment.center, - child: CircleAvatar( - backgroundColor: colors.primary.surface, - foregroundColor: colors.primary, - child: ZetaText.bodyMedium( - e == ZetaContrast.aa ? 'AA' : 'AAA', - textColor: colors.primary, - fontWeight: FontWeight.w700, - ), - ), - ); - }).toList(), - onChanged: (value) { - if (value != null) { - ZetaProvider.of(context).updateContrast(value); - } - }, - ), - ); - } -} diff --git a/example/lib/pages/theme_mode_switch.dart b/example/lib/pages/theme_mode_switch.dart deleted file mode 100644 index 392d7e12..00000000 --- a/example/lib/pages/theme_mode_switch.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -class ZetaThemeModeSwitch extends StatelessWidget { - ZetaThemeModeSwitch({super.key}); - - late final _themes = [ - ThemeMode.system, - ThemeMode.light, - ThemeMode.dark, - ]; - - @override - Widget build(BuildContext context) { - var zeta = Zeta.of(context); - - ZetaColors zetaColors(ThemeMode mode) { - if ((mode == ThemeMode.system && MediaQuery.of(context).platformBrightness == Brightness.light) || - mode == ThemeMode.light) { - return zeta.themeData.colorsLight; - } else { - return zeta.themeData.colorsDark; - } - } - - return DropdownButtonHideUnderline( - child: DropdownButton( - value: zeta.themeMode, - elevation: 0, - isDense: true, - alignment: Alignment.center, - icon: SizedBox(width: 8), - dropdownColor: zeta.colors.borderDisabled, - items: _themes.map((e) { - final colors = zetaColors(e); - return DropdownMenuItem( - value: e, - alignment: Alignment.center, - child: CircleAvatar( - backgroundColor: colors.primary.surface, - foregroundColor: colors.primary, - child: Icon( - e == ThemeMode.system - ? Icons.system_security_update_good - : e == ThemeMode.light - ? Icons.light_mode - : Icons.dark_mode, - color: colors.primary), - ), - ); - }).toList(), - onChanged: (value) { - if (value != null) { - ZetaProvider.of(context).updateThemeMode(value); - } - }, - ), - ); - } -} diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 00000000..eefcc6d7 --- /dev/null +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,16 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import path_provider_foundation +import shared_preferences_foundation +import sqflite + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) +} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 3417104f..507d869a 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -42,10 +42,7 @@ class HotReload extends StatelessWidget { WidgetbookCategory( name: 'Theme', isInitiallyExpanded: false, - children: [ - textWidgetBook(), - colorWidgetBook(), - ], + children: [textWidgetBook(), colorWidgetBook(), checkboxWidgetBook()], ), ], addons: [ diff --git a/lib/src/assets/fonts/zeta-icons-other.ttf b/lib/src/assets/fonts/zeta-icons-other.ttf deleted file mode 100644 index ba841bf80e29331887cdca0c3d6550b2310c5adb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1088 zcma)5O=}ZT6g_V~k~Rrxk=THwI@Yw6EMkahwICRR6be>D)ojfqohE@~W=v8@7eW?- zE))x{1YNjwA^rdtS?R`&{s9qJ#kEU`=gmw@3@&`(y?f5N_r81Q&IAHL6ho-U-M(`v zKX*#cQ2D@Jt#?c}S^4@H5GnGz4YTLc&XY?!(`X;;Z9IJYhI~N&s%e?K%b%X9fRZ3z zZ&C=C)Q{vh$r~jq$naXqDil4YFX2~a)n4e@47l9+Fqwxqum79v3#qlycAgjrp zqR+Q1>2VELX(Q}c;ZMLg!ua=iObsVkjDI9G=1tx!AQ&|#HCASQX5-3+7xKRvGsYuz z$lNG9gUGM16;>`Rg-$0Hl1t&Z2!|HM`L)7oR;;clD7$W1?p&!f$YfMxGJ{e{6n(Mm zR%5YTI-RRl?inV9PfgA1^Dg*tRNg@%QvPY7w8&sJ-|BW zC3$RLkEx;OaGr&3)nC-`hsNV>11O+^8)g8Ns z78`J2qgS!Iy_RDe`D_6dSga|X(q$lzEDBTcQ*_5_?6=J>c9`10KH4zRor>9X?7q>k zY^!VbtzDybU~JW$ZO5^**z_v(S*yVdY_GnFKJ6~G8V-1Fd97|UQg)T)oV@>=Klp#0 Fe*o3hoJ{}# diff --git a/lib/src/components/bottom sheets/bottom_sheet.dart b/lib/src/components/bottom sheets/bottom_sheet.dart index 9af8c853..db1447c2 100644 --- a/lib/src/components/bottom sheets/bottom_sheet.dart +++ b/lib/src/components/bottom sheets/bottom_sheet.dart @@ -66,7 +66,10 @@ class ZetaBottomSheet extends StatelessWidget { style: ZetaTextStyles.titleMedium, ), ), - Material(child: body ?? const SizedBox()), + Material( + color: colors.surfaceSecondary, + child: body ?? const SizedBox(), + ), ], ), ); diff --git a/lib/src/components/buttons/fab.dart b/lib/src/components/buttons/fab.dart index 6e383829..2d7eb2b7 100644 --- a/lib/src/components/buttons/fab.dart +++ b/lib/src/components/buttons/fab.dart @@ -125,7 +125,7 @@ class _ZetaFABState extends State { padding: EdgeInsets.zero, shape: widget.shape.buttonShape(isExpanded: _isExpanded, size: widget.size), backgroundColor: backgroundColor, - foregroundColor: colors.shade60.onColor, + foregroundColor: backgroundColor.onColor, ).copyWith( overlayColor: MaterialStateProperty.resolveWith((Set states) { if (states.contains(MaterialState.hovered)) return colors.hover; From 5dc334426f22dff048ca4553312eea0652ee1b79 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 2 Feb 2024 15:40:51 +0000 Subject: [PATCH 41/41] [automated commit] lint format and import sort --- .../Flutter/GeneratedPluginRegistrant.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 example/macos/Flutter/GeneratedPluginRegistrant.swift diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 00000000..eefcc6d7 --- /dev/null +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,16 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import path_provider_foundation +import shared_preferences_foundation +import sqflite + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) +}