Skip to content

Commit

Permalink
refactor: extract title text field
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasn committed Jun 16, 2024
1 parent d6b698f commit 6e899fd
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 67 deletions.
72 changes: 6 additions & 66 deletions lib/features/tasks/ui/checkbox_items_list.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:lotti/features/tasks/ui/checkbox_item_wrapper.dart';
import 'package:lotti/l10n/app_localizations_context.dart';
import 'package:lotti/themes/theme.dart';
import 'package:lotti/features/tasks/ui/title_text_field.dart';

class CheckboxItemsList extends StatefulWidget {
const CheckboxItemsList({
Expand All @@ -16,9 +15,6 @@ class CheckboxItemsList extends StatefulWidget {
}

class _CheckboxItemsListState extends State<CheckboxItemsList> {
final _controller = TextEditingController();
bool _isEditing = false;

@override
Widget build(BuildContext context) {
return ExpansionTile(
Expand All @@ -28,67 +24,11 @@ class _CheckboxItemsListState extends State<CheckboxItemsList> {
semanticsLabel: 'Checklist progress',
),
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 10,
),
child: TextField(
controller: _controller,
onChanged: (value) {
setState(() {
_isEditing = value.isNotEmpty;
});
},
decoration: inputDecoration(
labelText: context.messages.checklistAddItem,
semanticsLabel: 'Add item to checklist',
themeData: Theme.of(context),
).copyWith(
floatingLabelBehavior: FloatingLabelBehavior.never,
suffixIcon: AnimatedOpacity(
curve: Curves.easeInOutQuint,
opacity: _isEditing ? 1.0 : 0.0,
duration: const Duration(milliseconds: 400),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
icon: const Icon(
Icons.check_circle,
size: 30,
semanticLabel: 'add item',
),
onPressed: () {
debugPrint('Add item to checklist');
},
),
IconButton(
icon: const Icon(
Icons.cancel_outlined,
size: 30,
semanticLabel: 'discard changes',
),
onPressed: () {
_controller.clear();
setState(() {
_isEditing = false;
});
},
),
],
),
),
),
showCursor: true,
minLines: 1,
maxLines: 3,
textInputAction: TextInputAction.done,
onSubmitted: (value) {
debugPrint('Submitted: $value');
},
),
TitleTextField(
onSave: (title) {
debugPrint('Saved: $title');
},
semanticsLabel: 'Add item to checklist',
),
...widget.itemIds.map(CheckboxItemWrapper.new),
],
Expand Down
89 changes: 89 additions & 0 deletions lib/features/tasks/ui/title_text_field.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import 'package:flutter/material.dart';
import 'package:lotti/l10n/app_localizations_context.dart';
import 'package:lotti/themes/theme.dart';

typedef StringCallback = void Function(String);

class TitleTextField extends StatefulWidget {
const TitleTextField({
required this.onSave,
this.semanticsLabel,
super.key,
});

final StringCallback onSave;
final String? semanticsLabel;

@override
State<TitleTextField> createState() => _TitleTextFieldState();
}

class _TitleTextFieldState extends State<TitleTextField> {
final _controller = TextEditingController();
bool _isEditing = false;

@override
Widget build(BuildContext context) {
void onSave(String? value) {
widget.onSave(value ?? _controller.text);
setState(() => _isEditing = false);
}

return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 10,
),
child: TextField(
controller: _controller,
onChanged: (value) {
setState(() {
_isEditing = value.isNotEmpty;
});
},
decoration: inputDecoration(
labelText: context.messages.checklistAddItem,
semanticsLabel: widget.semanticsLabel,
themeData: Theme.of(context),
).copyWith(
floatingLabelBehavior: FloatingLabelBehavior.never,
suffixIcon: AnimatedOpacity(
curve: Curves.easeInOutQuint,
opacity: _isEditing ? 1.0 : 0.0,
duration: const Duration(milliseconds: 400),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
icon: const Icon(
Icons.check_circle,
size: 30,
semanticLabel: 'save item',
),
onPressed: () => onSave(_controller.text),
),
IconButton(
icon: const Icon(
Icons.cancel_outlined,
size: 30,
semanticLabel: 'discard changes',
),
onPressed: () {
_controller.clear();
setState(() => _isEditing = false);
},
),
],
),
),
),
showCursor: true,
minLines: 1,
maxLines: 3,
textInputAction: TextInputAction.done,
onSubmitted: onSave,
),
);
}
}
11 changes: 10 additions & 1 deletion lib/widgetbook.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lotti/features/tasks/state/checklist_item_controller.dart';
import 'package:lotti/features/tasks/ui/checkbox_item_widget.dart';
import 'package:lotti/features/tasks/ui/checkbox_items_list.dart';
import 'package:lotti/features/tasks/ui/title_text_field.dart';
import 'package:lotti/get_it.dart';
import 'package:lotti/services/db_notification.dart';
import 'package:lotti/widgetbook/mock_controllers.dart';
Expand Down Expand Up @@ -58,7 +59,7 @@ class WidgetbookApp extends StatelessWidget {
name: 'Checkbox widget',
useCases: [
WidgetbookUseCase(
name: 'UI implementation',
name: 'CheckboxItemWidget',
builder: (context) => CheckboxItemWidget(
title: 'Create PR',
isChecked: true,
Expand All @@ -68,6 +69,14 @@ class WidgetbookApp extends StatelessWidget {
},
),
),
WidgetbookUseCase(
name: 'TitleTextField',
builder: (context) => TitleTextField(
onSave: (title) {
debugPrint('Saved: $title');
},
),
),
WidgetbookUseCase(
name: 'With provider wrapper',
builder: (context) => ProviderScope(
Expand Down

0 comments on commit 6e899fd

Please sign in to comment.