From 84b727ce67cfbcc35c1ca12979331e3bc9fa4f4a Mon Sep 17 00:00:00 2001 From: sd-athlon <163880004+sd-athlon@users.noreply.github.com> Date: Tue, 30 Apr 2024 13:29:46 +0300 Subject: [PATCH] main: Contact List (#40) * feat(main): Contact List * [automated commit] lint format and import sort --------- Co-authored-by: github-actions --- example/lib/home.dart | 2 + .../components/contact_item_example.dart | 27 +++++ example/widgetbook/main.dart | 2 + .../components/contact_item_widgetbook.dart | 21 ++++ .../components/contact_item/contact_item.dart | 100 ++++++++++++++++++ lib/zeta_flutter.dart | 1 + 6 files changed, 153 insertions(+) create mode 100644 example/lib/pages/components/contact_item_example.dart create mode 100644 example/widgetbook/pages/components/contact_item_widgetbook.dart create mode 100644 lib/src/components/contact_item/contact_item.dart diff --git a/example/lib/home.dart b/example/lib/home.dart index 8d76134b..dd349a64 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -10,6 +10,7 @@ import 'package:zeta_example/pages/components/breadcrumbs_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'; +import 'package:zeta_example/pages/components/contact_item_example.dart'; import 'package:zeta_example/pages/components/date_input_example.dart'; import 'package:zeta_example/pages/components/dialog_example.dart'; import 'package:zeta_example/pages/components/dialpad_example.dart'; @@ -58,6 +59,7 @@ final List components = [ Component(ButtonExample.name, (context) => const ButtonExample()), Component(CheckBoxExample.name, (context) => const CheckBoxExample()), Component(ChipExample.name, (context) => const ChipExample()), + Component(ContactItemExample.name, (context) => const ContactItemExample()), Component(ListItemExample.name, (context) => const ListItemExample()), Component(NavigationBarExample.name, (context) => const NavigationBarExample()), Component(PaginationExample.name, (context) => const PaginationExample()), diff --git a/example/lib/pages/components/contact_item_example.dart b/example/lib/pages/components/contact_item_example.dart new file mode 100644 index 00000000..cc566218 --- /dev/null +++ b/example/lib/pages/components/contact_item_example.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:zeta_example/widgets.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +class ContactItemExample extends StatefulWidget { + static const String name = 'ContactItem'; + + const ContactItemExample({super.key}); + + @override + State createState() => _ContactItemExampleState(); +} + +class _ContactItemExampleState extends State { + @override + Widget build(BuildContext context) { + return ExampleScaffold( + name: ContactItemExample.name, + child: ZetaContactItem( + onTap: () {}, + leading: ZetaAvatar(size: ZetaAvatarSize.s), + title: Text("Contact / Group Name"), + subtitle: Text("Store Associate - Bakery Dept."), + ), + ); + } +} diff --git a/example/widgetbook/main.dart b/example/widgetbook/main.dart index 6d1f72fe..38719607 100644 --- a/example/widgetbook/main.dart +++ b/example/widgetbook/main.dart @@ -13,6 +13,7 @@ import 'pages/components/breadcrumbs_widgetbook.dart'; import 'pages/components/button_widgetbook.dart'; import 'pages/components/checkbox_widgetbook.dart'; import 'pages/components/chip_widgetbook.dart'; +import 'pages/components/contact_item_widgetbook.dart'; import 'pages/components/date_input_widgetbook.dart'; import 'pages/components/dial_pad_widgetbook.dart'; import 'pages/components/dialog_widgetbook.dart'; @@ -83,6 +84,7 @@ class HotReload extends StatelessWidget { ), WidgetbookUseCase(name: 'Avatar', builder: (context) => avatarUseCase(context)), WidgetbookUseCase(name: 'Checkbox', builder: (context) => checkboxUseCase(context)), + WidgetbookUseCase(name: 'Contact Item', builder: (context) => contactItemUseCase(context)), WidgetbookComponent( name: 'Buttons', useCases: [ diff --git a/example/widgetbook/pages/components/contact_item_widgetbook.dart b/example/widgetbook/pages/components/contact_item_widgetbook.dart new file mode 100644 index 00000000..d41fa8c7 --- /dev/null +++ b/example/widgetbook/pages/components/contact_item_widgetbook.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; + +Widget contactItemUseCase(BuildContext context) { + final title = context.knobs.string(label: 'Title', initialValue: "Contact / Group Name"); + final subtitle = context.knobs.string(label: 'Subtitle', initialValue: "Store Associate - Bakery Dept."); + final enabledDivider = context.knobs.boolean(label: 'Enabled Divider', initialValue: true); + + return WidgetbookTestWidget( + widget: ZetaContactItem( + onTap: () {}, + leading: ZetaAvatar(size: ZetaAvatarSize.s), + title: Text(title), + subtitle: Text(subtitle), + enabledDivider: enabledDivider, + ), + ); +} diff --git a/lib/src/components/contact_item/contact_item.dart b/lib/src/components/contact_item/contact_item.dart new file mode 100644 index 00000000..ac1d2bcc --- /dev/null +++ b/lib/src/components/contact_item/contact_item.dart @@ -0,0 +1,100 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import '../../../zeta_flutter.dart'; + +/// A single row that contains avatar, title and subtitle. +class ZetaContactItem extends StatelessWidget { + /// Constructs [ZetaContactItem]. + const ZetaContactItem({ + required this.title, + required this.leading, + required this.subtitle, + this.enabledDivider = true, + this.onTap, + super.key, + }); + + /// The main text to be displayed on the top. + final Widget title; + + /// Normally an Avatar + final Widget leading; + + /// Text to be displayed under [title]. + final Widget subtitle; + + /// Callback to be called onTap. + final VoidCallback? onTap; + + /// Whether to display a divider at the bottom. + final bool enabledDivider; + + @override + Widget build(BuildContext context) { + final colors = Zeta.of(context).colors; + + return DecoratedBox( + decoration: BoxDecoration( + color: colors.surfacePrimary, + border: enabledDivider + ? Border( + bottom: BorderSide(color: colors.borderDisabled), + ) + : null, + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.only( + top: ZetaSpacing.xs, + bottom: ZetaSpacing.xs, + left: ZetaSpacing.m, + ), + child: Row( + children: [ + leading, + Flexible( + child: Padding( + padding: const EdgeInsets.only(left: ZetaSpacing.s), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + DefaultTextStyle( + style: ZetaTextStyles.bodyMedium.copyWith( + color: colors.textDefault, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + child: title, + ), + DefaultTextStyle( + style: ZetaTextStyles.bodySmall.copyWith( + color: colors.textSubtle, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + child: subtitle, + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(ObjectFlagProperty.has('onTap', onTap)) + ..add(DiagnosticsProperty('enabledDivider', enabledDivider)); + } +} diff --git a/lib/zeta_flutter.dart b/lib/zeta_flutter.dart index cb37ebfd..48a3c902 100644 --- a/lib/zeta_flutter.dart +++ b/lib/zeta_flutter.dart @@ -23,6 +23,7 @@ export 'src/components/buttons/fab.dart'; export 'src/components/buttons/icon_button.dart'; export 'src/components/checkbox/checkbox.dart'; export 'src/components/chips/chip.dart'; +export 'src/components/contact_item/contact_item.dart'; export 'src/components/date_input/date_input.dart'; export 'src/components/dial_pad/dial_pad.dart'; export 'src/components/dialog/dialog.dart';