Skip to content

Commit

Permalink
feat: Created dropdown list item (#101)
Browse files Browse the repository at this point in the history
feat: Created ZetaAnimationDuration tokens
  • Loading branch information
mikecoomber authored Jun 12, 2024
1 parent ccb3fe9 commit 868b26c
Show file tree
Hide file tree
Showing 16 changed files with 381 additions and 78 deletions.
22 changes: 20 additions & 2 deletions example/lib/pages/components/list_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,29 @@ class ListExample extends StatelessWidget {
return ExampleScaffold(
name: 'List',
child: ZetaList(
showDivider: false,
showDivider: true,
items: [
ZetaListItem(primaryText: 'Item 1'),
ZetaListItem(primaryText: 'Item 2'),
ZetaListItem(primaryText: 'Item 3', showDivider: true),
ZetaDropdownListItem(
primaryText: 'Item 3',
leading: Icon(ZetaIcons.star_round),
expanded: true,
items: [
ZetaListItem.checkbox(
primaryText: 'Dropdown Item 1',
onChanged: (_) {},
),
ZetaListItem.checkbox(
primaryText: 'Dropdown Item 2',
onChanged: (_) {},
),
ZetaListItem.checkbox(
primaryText: 'Dropdown Item 3',
onChanged: (_) {},
),
],
),
ZetaListItem(primaryText: 'Item 4', showDivider: true),
ZetaListItem(primaryText: 'Item 5'),
ZetaListItem(primaryText: 'Item 6'),
Expand Down
66 changes: 41 additions & 25 deletions example/lib/pages/components/list_item_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,31 +66,47 @@ class _ListItemExampleState extends State<ListItemExample> {
},
)),
_buildListItem(
'Radio Right',
Column(
children: [
ZetaListItem.radio(
primaryText: 'Radio option 1',
value: radioOption1,
groupValue: radioGroupValue,
onChanged: (value) {
setState(() {
radioGroupValue = value;
});
},
),
ZetaListItem.radio(
primaryText: 'Radio option 2',
value: radioOption2,
groupValue: radioGroupValue,
onChanged: (value) {
setState(() {
radioGroupValue = value;
});
},
),
],
)),
'Radio Right',
Column(
children: [
ZetaListItem.radio(
primaryText: 'Radio option 1',
value: radioOption1,
groupValue: radioGroupValue,
onChanged: (value) {
setState(() {
radioGroupValue = value;
});
},
),
ZetaListItem.radio(
primaryText: 'Radio option 2',
value: radioOption2,
groupValue: radioGroupValue,
onChanged: (value) {
setState(() {
radioGroupValue = value;
});
},
),
],
),
),
_buildListItem(
'Dropdown list',
ZetaDropdownListItem(
items: [
ZetaListItem(primaryText: 'List Item'),
ZetaListItem(primaryText: 'List Item'),
ZetaListItem(primaryText: 'List Item'),
],
expanded: true,
primaryText: 'List Item',
leading: Icon(
ZetaIcons.star_round,
),
),
),
].divide(const SizedBox(height: 16)).toList(),
),
),
Expand Down
2 changes: 1 addition & 1 deletion example/lib/pages/theme/color_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ class MyRow extends StatelessWidget {
height: 160,
width: 160,
color: e.value,
duration: const Duration(milliseconds: 250),
duration: ZetaAnimationLength.fast,
child: FittedBox(
fit: BoxFit.scaleDown,
child: Column(
Expand Down
9 changes: 8 additions & 1 deletion example/widgetbook/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:zeta_flutter/zeta_flutter.dart';

import 'pages/assets/icon_widgetbook.dart';
import 'pages/components/accordion_widgetbook.dart';
import 'pages/components/dropdown_list_item_widgetbook.dart';
import 'pages/components/notification_list_item_widgetbook.dart';
import 'pages/components/text_input_widgetbook.dart';
import 'pages/components/top_app_bar_widgetbook.dart';
Expand Down Expand Up @@ -159,7 +160,13 @@ class _HotReloadState extends State<HotReload> {
useCases: [
WidgetbookUseCase(name: 'List Item', builder: (context) => listItemUseCase(context)),
WidgetbookUseCase(
name: 'Notification List Item', builder: (context) => notificationListItemUseCase(context)),
name: 'Dropdown List Item',
builder: (context) => dropdownListItemUseCase(context),
),
WidgetbookUseCase(
name: 'Notification List Item',
builder: (context) => notificationListItemUseCase(context),
),
WidgetbookUseCase(name: 'Contact Item', builder: (context) => contactItemUseCase(context)),
WidgetbookUseCase(name: 'Chat List Item', builder: (context) => chatItemWidgetBook(context)),
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:widgetbook/widgetbook.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

import '../../test/test_components.dart';
import '../../utils/utils.dart';

Widget dropdownListItemUseCase(BuildContext context) {
return WidgetbookTestWidget(
widget: StatefulBuilder(
builder: (context, setState) {
final primaryText = context.knobs.string(label: 'Primary text', initialValue: 'Label');

final secondaryText = context.knobs.string(label: 'Secondary text', initialValue: 'Descriptor');

final showIcon = context.knobs.boolean(label: 'Show icon');

final showDivider = context.knobs.boolean(label: 'Show divider');

final rounded = roundedKnob(context);

final leading = showIcon ? Icon(ZetaIcons.star_round) : null;

return ZetaDropdownListItem(
primaryText: primaryText,
items: [
ZetaListItem(primaryText: 'List Item'),
ZetaListItem(primaryText: 'List Item'),
ZetaListItem(primaryText: 'List Item'),
],
rounded: rounded,
secondaryText: secondaryText,
leading: leading,
showDivider: showDivider,
);
},
),
);
}
4 changes: 2 additions & 2 deletions lib/src/components/accordion/accordion.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class _ZetaAccordionState extends State<ZetaAccordion> with TickerProviderStateM
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 300),
reverseDuration: const Duration(milliseconds: 200),
duration: ZetaAnimationLength.normal,
reverseDuration: ZetaAnimationLength.fast,
vsync: this,
);
_animation = CurvedAnimation(
Expand Down
4 changes: 2 additions & 2 deletions lib/src/components/checkbox/checkbox.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class _CheckboxState extends State<_Checkbox> {
onTap: !widget.disabled ? () => widget.onChanged.call(!_checked) : null,
borderRadius: ZetaRadius.full,
child: Padding(
padding: const EdgeInsets.all(ZetaSpacing.small),
padding: const EdgeInsets.all(ZetaSpacing.medium),
child: Semantics(
mixed: widget.useIndeterminate,
enabled: !widget.disabled,
Expand Down Expand Up @@ -194,7 +194,7 @@ class _CheckboxState extends State<_Checkbox> {
mainAxisSize: MainAxisSize.min,
children: [
AnimatedContainer(
duration: const Duration(milliseconds: 200),
duration: ZetaAnimationLength.fast,
decoration: BoxDecoration(
boxShadow: [
if (_isFocused && !widget.disabled)
Expand Down
2 changes: 1 addition & 1 deletion lib/src/components/fabs/fab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class _ZetaFABState extends State<ZetaFAB> {
),
),
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
duration: ZetaAnimationLength.normal,
child: Padding(
padding: _isExpanded
? const EdgeInsets.symmetric(horizontal: ZetaSpacingBase.x3_5, vertical: ZetaSpacing.medium)
Expand Down
164 changes: 164 additions & 0 deletions lib/src/components/list_item/dropdown_list_item.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import '../../assets/icons.dart';
import '../../theme/tokens.dart';
import '../../zeta.dart';
import 'list_item.dart';
import 'list_scope.dart';

/// An expandable list item containing other [ZetaListItem]s within it.
class ZetaDropdownListItem extends StatefulWidget {
/// Creates a new [ZetaDropdownListItem]
const ZetaDropdownListItem({
required this.primaryText,
required this.items,
this.secondaryText,
this.expanded = false,
this.leading,
this.rounded = true,
this.showDivider,
super.key,
});

/// The list of [ZetaListItem]s contained within the dropdown.
final List<ZetaListItem> items;

/// {@macro list-item-primary-text}
final String primaryText;

/// {@macro list-item-secondary-text}
final String? secondaryText;

/// {@macro list-item-leading}
final Widget? leading;

/// Expands the list item if set to true.
/// Defaults to false.
final bool expanded;

/// {@macro zeta-component-rounded}
final bool rounded;

/// {@macro list-item-show-divider}
final bool? showDivider;

@override
State<ZetaDropdownListItem> createState() => _ZetaDropdownListItemState();
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(IterableProperty<ZetaListItem>('items', items))
..add(StringProperty('primaryText', primaryText))
..add(StringProperty('secondaryText', secondaryText))
..add(DiagnosticsProperty<bool>('expanded', expanded))
..add(DiagnosticsProperty<bool>('rounded', rounded))
..add(DiagnosticsProperty<bool?>('showDivider', showDivider));
}
}

class _ZetaDropdownListItemState extends State<ZetaDropdownListItem> with SingleTickerProviderStateMixin {
late AnimationController _expandController;
late Animation<double> _animation;

late bool _expanded;

IconData get _icon {
return widget.rounded ? ZetaIcons.expand_more_round : ZetaIcons.expand_more_sharp;
}

@override
void initState() {
_expanded = widget.expanded;
_expandController = AnimationController(
vsync: this,
duration: ZetaAnimationLength.fast,
);
_animation = CurvedAnimation(
parent: _expandController,
curve: Curves.easeInOut,
);
if (_expanded) {
_expandController.value = 1;
}
super.initState();
}

@override
void didUpdateWidget(covariant ZetaDropdownListItem oldWidget) {
if (oldWidget.expanded != widget.expanded) {
_setExpanded(widget.expanded);
}
super.didUpdateWidget(oldWidget);
}

@override
void dispose() {
_expandController.dispose();
super.dispose();
}

void _setExpanded(bool value) {
setState(() {
_expanded = value;
});
if (_expanded) {
_expandController.forward();
} else {
_expandController.reverse();
}
}

void _onTap() => _setExpanded(!_expanded);

@override
Widget build(BuildContext context) {
final divide = widget.showDivider ?? ListScope.of(context)?.showDivider ?? false;
final colors = Zeta.of(context).colors;

// DecoratedBox does not correctly animated the border when the widget expands.
// ignore: use_decorated_box
return Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: divide ? colors.borderDefault : Colors.transparent,
),
),
),
child: Column(
children: [
ZetaListItem(
primaryText: widget.primaryText,
secondaryText: widget.secondaryText,
leading: widget.leading,
onTap: _onTap,
showDivider: false,
trailing: IconButton(
icon: AnimatedRotation(
turns: _expanded ? 0.5 : 0,
duration: ZetaAnimationLength.fast,
child: Icon(
_icon,
color: colors.iconSubtle,
),
),
onPressed: _onTap,
),
),
ListScope(
showDivider: false,
indentItems: true,
child: SizeTransition(
sizeFactor: _animation,
child: Column(
children: widget.items,
),
),
),
],
),
);
}
}
Loading

0 comments on commit 868b26c

Please sign in to comment.