From 50a4f0393106983957d29fb3a29314e78b3aa163 Mon Sep 17 00:00:00 2001 From: Richard Shiue <71320345+richardshiue@users.noreply.github.com> Date: Wed, 13 Sep 2023 19:12:26 +0800 Subject: [PATCH] chore: date editor ui polish (#3367) --- .../row/cells/date_cell/date_editor.dart | 212 +++++++++--------- .../lib/style_widget/button.dart | 2 +- .../lib/style_widget/text_field.dart | 16 +- 3 files changed, 119 insertions(+), 111 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart index 1668f7b266..f7088e1731 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart @@ -10,7 +10,6 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:dartz/dartz.dart' show Either; import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra/time/duration.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -51,7 +50,7 @@ class _DateCellEditor extends State { if (snapshot.hasData) { return _buildWidget(snapshot); } else { - return const SizedBox(); + return const SizedBox.shrink(); } }, ); @@ -67,7 +66,7 @@ class _DateCellEditor extends State { }, (err) { Log.error(err); - return const SizedBox(); + return const SizedBox.shrink(); }, ); } @@ -108,10 +107,6 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> { child: BlocBuilder( builder: (context, state) { final List children = [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 12.0), - child: _buildCalendar(context), - ), AnimatedSwitcher( duration: const Duration(milliseconds: 300), child: state.includeTime @@ -121,11 +116,13 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> { ) : const SizedBox.shrink(), ), - const TypeOptionSeparator(spacing: 12.0), + const DatePicker(), + const VSpace(8.0), + const TypeOptionSeparator(spacing: 8.0), const _IncludeTimeButton(), - const TypeOptionSeparator(spacing: 12.0), + const TypeOptionSeparator(spacing: 8.0), DateTypeOptionButton(popoverMutex: popoverMutex), - const TypeOptionSeparator(spacing: 12.0), + VSpace(GridSize.typeOptionSeparatorHeight), const ClearDateButton(), ]; @@ -134,7 +131,7 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> { controller: ScrollController(), itemCount: children.length, itemBuilder: (BuildContext context, int index) => children[index], - padding: const EdgeInsets.symmetric(vertical: 12.0), + padding: const EdgeInsets.only(top: 18.0, bottom: 12.0), ); }, ), @@ -146,84 +143,103 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> { popoverMutex.dispose(); super.dispose(); } +} - Widget _buildCalendar(BuildContext context) { +class DatePicker extends StatelessWidget { + const DatePicker({super.key}); + + @override + Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { final textStyle = Theme.of(context).textTheme.bodyMedium!; final boxDecoration = BoxDecoration( color: Theme.of(context).colorScheme.surface, - shape: BoxShape.rectangle, - borderRadius: Corners.s6Border, + shape: BoxShape.circle, ); - return TableCalendar( - firstDay: kFirstDay, - lastDay: kLastDay, - focusedDay: state.focusedDay, - rowHeight: GridSize.popoverItemHeight, - calendarFormat: state.format, - daysOfWeekHeight: GridSize.popoverItemHeight, - headerStyle: HeaderStyle( - formatButtonVisible: false, - titleCentered: true, - titleTextStyle: textStyle, - leftChevronMargin: EdgeInsets.zero, - leftChevronPadding: EdgeInsets.zero, - leftChevronIcon: FlowySvg( - FlowySvgs.arrow_left_s, - color: Theme.of(context).iconTheme.color, + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: TableCalendar( + firstDay: kFirstDay, + lastDay: kLastDay, + focusedDay: state.focusedDay, + rowHeight: 26.0 + 7.0, + calendarFormat: state.format, + daysOfWeekHeight: 17.0 + 8.0, + headerStyle: HeaderStyle( + formatButtonVisible: false, + titleCentered: true, + titleTextStyle: textStyle, + leftChevronMargin: EdgeInsets.zero, + leftChevronPadding: EdgeInsets.zero, + leftChevronIcon: FlowySvg( + FlowySvgs.arrow_left_s, + color: Theme.of(context).iconTheme.color, + ), + rightChevronPadding: EdgeInsets.zero, + rightChevronMargin: EdgeInsets.zero, + rightChevronIcon: FlowySvg( + FlowySvgs.arrow_right_s, + color: Theme.of(context).iconTheme.color, + ), + headerMargin: EdgeInsets.zero, + headerPadding: const EdgeInsets.only(bottom: 8.0), ), - rightChevronPadding: EdgeInsets.zero, - rightChevronMargin: EdgeInsets.zero, - rightChevronIcon: FlowySvg( - FlowySvgs.arrow_right_s, - color: Theme.of(context).iconTheme.color, + calendarStyle: CalendarStyle( + cellMargin: const EdgeInsets.all(3.5), + defaultDecoration: boxDecoration, + selectedDecoration: boxDecoration.copyWith( + color: Theme.of(context).colorScheme.primary, + ), + todayDecoration: boxDecoration.copyWith( + color: Colors.transparent, + border: + Border.all(color: Theme.of(context).colorScheme.primary), + ), + weekendDecoration: boxDecoration, + outsideDecoration: boxDecoration, + defaultTextStyle: textStyle, + weekendTextStyle: textStyle, + selectedTextStyle: textStyle.copyWith( + color: Theme.of(context).colorScheme.surface, + ), + todayTextStyle: textStyle, + outsideTextStyle: textStyle.copyWith( + color: Theme.of(context).disabledColor, + ), ), - headerMargin: const EdgeInsets.only(bottom: 8.0), - ), - daysOfWeekStyle: DaysOfWeekStyle( - dowTextFormatter: (date, locale) => - DateFormat.E(locale).format(date).toUpperCase(), - weekdayStyle: AFThemeExtension.of(context).caption, - weekendStyle: AFThemeExtension.of(context).caption, - ), - calendarStyle: CalendarStyle( - cellMargin: const EdgeInsets.all(3), - defaultDecoration: boxDecoration, - selectedDecoration: boxDecoration.copyWith( - color: Theme.of(context).colorScheme.primary, - ), - todayDecoration: boxDecoration.copyWith( - color: AFThemeExtension.of(context).lightGreyHover, - ), - weekendDecoration: boxDecoration, - outsideDecoration: boxDecoration, - defaultTextStyle: textStyle, - weekendTextStyle: textStyle, - selectedTextStyle: textStyle.copyWith( - color: Theme.of(context).colorScheme.surface, - ), - todayTextStyle: textStyle, - outsideTextStyle: textStyle.copyWith( - color: Theme.of(context).disabledColor, - ), - ), - selectedDayPredicate: (day) => isSameDay(state.dateTime, day), - onDaySelected: (selectedDay, focusedDay) { - context.read().add( - DateCellCalendarEvent.selectDay(selectedDay.toLocal().date), + calendarBuilders: CalendarBuilders( + dowBuilder: (context, day) { + final locale = context.locale.toLanguageTag(); + final label = DateFormat.E(locale).format(day).substring(0, 2); + return Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Center( + child: Text( + label, + style: AFThemeExtension.of(context).caption, + ), + ), ); - }, - onFormatChanged: (format) { - context - .read() - .add(DateCellCalendarEvent.setCalFormat(format)); - }, - onPageChanged: (focusedDay) { - context - .read() - .add(DateCellCalendarEvent.setFocusedDay(focusedDay)); - }, + }, + ), + selectedDayPredicate: (day) => isSameDay(state.dateTime, day), + onDaySelected: (selectedDay, focusedDay) { + context.read().add( + DateCellCalendarEvent.selectDay(selectedDay.toLocal().date), + ); + }, + onFormatChanged: (format) { + context + .read() + .add(DateCellCalendarEvent.setCalFormat(format)); + }, + onPageChanged: (focusedDay) { + context + .read() + .add(DateCellCalendarEvent.setFocusedDay(focusedDay)); + }, + ), ); }, ); @@ -295,26 +311,21 @@ class _TimeTextFieldState extends State<_TimeTextField> { return BlocConsumer( listener: (context, state) => _textController.text = state.time ?? "", builder: (context, state) { - return Column( - children: [ - const VSpace(12), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 12.0), - child: FlowyTextField( - text: state.time ?? "", - focusNode: _focusNode, - controller: _textController, - submitOnLeave: true, - hintText: state.timeHintText, - errorText: state.timeFormatError, - onSubmitted: (timeStr) { - context - .read() - .add(DateCellCalendarEvent.setTime(timeStr)); - }, - ), - ), - ], + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 18.0), + child: FlowyTextField( + text: state.time ?? "", + focusNode: _focusNode, + controller: _textController, + submitOnLeave: true, + hintText: state.timeHintText, + errorText: state.timeFormatError, + onSubmitted: (timeStr) { + context + .read() + .add(DateCellCalendarEvent.setTime(timeStr)); + }, + ), ); }, ); @@ -349,7 +360,6 @@ class DateTypeOptionButton extends StatelessWidget { height: GridSize.popoverItemHeight, child: FlowyButton( text: FlowyText.medium(title), - margin: GridSize.typeOptionContentInsets, rightIcon: const FlowySvg(FlowySvgs.more_s), ), ), @@ -461,8 +471,6 @@ class ClearDateButton extends StatelessWidget { .add(const DateCellCalendarEvent.clearDate()); PopoverContainer.of(context).close(); }, - leftIcon: const FlowySvg(FlowySvgs.delete_s), - margin: GridSize.typeOptionContentInsets, ), ), ); diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart index 86f891d5c8..a11ffe9879 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -100,7 +100,7 @@ class FlowyButton extends StatelessWidget { decoration: decoration, child: Padding( padding: - margin ?? const EdgeInsets.symmetric(horizontal: 10, vertical: 2), + margin ?? const EdgeInsets.symmetric(horizontal: 6, vertical: 4), child: child, ), ); diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart index 562f1f403c..7bf05d64e0 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart @@ -105,18 +105,18 @@ class FlowyTextFieldState extends State { maxLines: widget.maxLines, maxLength: widget.maxLength, maxLengthEnforcement: MaxLengthEnforcement.truncateAfterCompositionEnds, - style: Theme.of(context).textTheme.bodyMedium, + style: Theme.of(context).textTheme.bodySmall, decoration: InputDecoration( - contentPadding: - const EdgeInsets.symmetric(horizontal: 10, vertical: 13), + constraints: const BoxConstraints(maxHeight: 32), + contentPadding: const EdgeInsets.symmetric(horizontal: 12), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.outline, width: 1.0, ), - borderRadius: Corners.s10Border, + borderRadius: Corners.s8Border, ), - isDense: true, + isDense: false, hintText: widget.hintText, errorText: widget.errorText, hintStyle: Theme.of(context) @@ -130,21 +130,21 @@ class FlowyTextFieldState extends State { color: Theme.of(context).colorScheme.primary, width: 1.0, ), - borderRadius: Corners.s10Border, + borderRadius: Corners.s8Border, ), errorBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.error, width: 1.0, ), - borderRadius: Corners.s10Border, + borderRadius: Corners.s8Border, ), focusedErrorBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.error, width: 1.0, ), - borderRadius: Corners.s10Border, + borderRadius: Corners.s8Border, ), ), );