Browse Source

chore: add close button in select option tags for select option textfield (#1640)

* chore: remove unused isSelected flag

* chore: close popover when an option is deleted

* chore: allow unselecting an option by clicking on a close button
Richard Shiue 2 năm trước cách đây
mục cha
commit
1a2af1cf49

+ 32 - 6
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart

@@ -1,6 +1,8 @@
+import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
+import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
@@ -62,13 +64,13 @@ extension SelectOptionColorExtension on SelectOptionColorPB {
 class SelectOptionTag extends StatelessWidget {
 class SelectOptionTag extends StatelessWidget {
   final String name;
   final String name;
   final Color color;
   final Color color;
-  final bool isSelected;
   final VoidCallback? onSelected;
   final VoidCallback? onSelected;
+  final void Function(String)? onRemove;
   const SelectOptionTag({
   const SelectOptionTag({
     required this.name,
     required this.name,
     required this.color,
     required this.color,
     this.onSelected,
     this.onSelected,
-    this.isSelected = false,
+    this.onRemove,
     Key? key,
     Key? key,
   }) : super(key: key);
   }) : super(key: key);
 
 
@@ -76,25 +78,49 @@ class SelectOptionTag extends StatelessWidget {
     required BuildContext context,
     required BuildContext context,
     required SelectOptionPB option,
     required SelectOptionPB option,
     VoidCallback? onSelected,
     VoidCallback? onSelected,
-    bool isSelected = false,
+    Function(String)? onRemove,
   }) {
   }) {
     return SelectOptionTag(
     return SelectOptionTag(
       name: option.name,
       name: option.name,
       color: option.color.make(context),
       color: option.color.make(context),
-      isSelected: isSelected,
       onSelected: onSelected,
       onSelected: onSelected,
+      onRemove: onRemove,
     );
     );
   }
   }
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
+    EdgeInsets padding =
+        const EdgeInsets.symmetric(vertical: 2.0, horizontal: 8.0);
+    if (onRemove != null) {
+      padding = padding.copyWith(right: 2.0);
+    }
+
     return Container(
     return Container(
-      padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 8.0),
+      padding: padding,
       decoration: BoxDecoration(
       decoration: BoxDecoration(
         color: color,
         color: color,
         borderRadius: Corners.s6Border,
         borderRadius: Corners.s6Border,
       ),
       ),
-      child: FlowyText.medium(name, overflow: TextOverflow.ellipsis),
+      child: Row(
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          Flexible(
+            child: FlowyText.medium(name, overflow: TextOverflow.ellipsis),
+          ),
+          if (onRemove != null)
+            FlowyIconButton(
+              width: 18.0,
+              onPressed: () => onRemove?.call(name),
+              fillColor: Colors.transparent,
+              hoverColor: Colors.transparent,
+              icon: svgWidget(
+                'home/close',
+                color: Theme.of(context).colorScheme.onSurface,
+              ),
+            ),
+        ],
+      ),
     );
     );
   }
   }
 }
 }

+ 8 - 0
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart

@@ -159,6 +159,13 @@ class _TextField extends StatelessWidget {
                     remainder,
                     remainder,
                   ));
                   ));
             },
             },
+            onRemove: (optionName) {
+              context
+                  .read<SelectOptionCellEditorBloc>()
+                  .add(SelectOptionEditorEvent.unSelectOption(
+                    optionMap[optionName]!.id,
+                  ));
+            },
           ),
           ),
         );
         );
       },
       },
@@ -297,6 +304,7 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
             context
             context
                 .read<SelectOptionCellEditorBloc>()
                 .read<SelectOptionCellEditorBloc>()
                 .add(SelectOptionEditorEvent.deleteOption(widget.option));
                 .add(SelectOptionEditorEvent.deleteOption(widget.option));
+            PopoverContainer.of(popoverContext).close();
           },
           },
           onUpdated: (updatedOption) {
           onUpdated: (updatedOption) {
             context
             context

+ 26 - 18
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/text_field.dart

@@ -22,6 +22,7 @@ class SelectOptionTextField extends StatefulWidget {
   final Function(String) onSubmitted;
   final Function(String) onSubmitted;
   final Function(String) newText;
   final Function(String) newText;
   final Function(List<String>, String) onPaste;
   final Function(List<String>, String) onPaste;
+  final Function(String) onRemove;
   final VoidCallback? onClick;
   final VoidCallback? onClick;
   final int? maxLength;
   final int? maxLength;
 
 
@@ -32,6 +33,7 @@ class SelectOptionTextField extends StatefulWidget {
     required this.tagController,
     required this.tagController,
     required this.onSubmitted,
     required this.onSubmitted,
     required this.onPaste,
     required this.onPaste,
+    required this.onRemove,
     required this.newText,
     required this.newText,
     required this.textSeparators,
     required this.textSeparators,
     this.onClick,
     this.onClick,
@@ -163,25 +165,31 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
     }
     }
 
 
     final children = widget.selectedOptionMap.values
     final children = widget.selectedOptionMap.values
-        .map((option) =>
-            SelectOptionTag.fromOption(context: context, option: option))
+        .map((option) => SelectOptionTag.fromOption(
+              context: context,
+              option: option,
+              onRemove: (option) => widget.onRemove(option),
+            ))
         .toList();
         .toList();
-    return Padding(
-      padding: const EdgeInsets.all(8.0),
-      child: ScrollConfiguration(
-        behavior: ScrollConfiguration.of(context).copyWith(
-          dragDevices: {
-            PointerDeviceKind.mouse,
-            PointerDeviceKind.touch,
-            PointerDeviceKind.trackpad,
-            PointerDeviceKind.stylus,
-            PointerDeviceKind.invertedStylus,
-          },
-        ),
-        child: SingleChildScrollView(
-          controller: sc,
-          scrollDirection: Axis.horizontal,
-          child: Wrap(spacing: 4, children: children),
+    return MouseRegion(
+      cursor: SystemMouseCursors.basic,
+      child: Padding(
+        padding: const EdgeInsets.all(8.0),
+        child: ScrollConfiguration(
+          behavior: ScrollConfiguration.of(context).copyWith(
+            dragDevices: {
+              PointerDeviceKind.mouse,
+              PointerDeviceKind.touch,
+              PointerDeviceKind.trackpad,
+              PointerDeviceKind.stylus,
+              PointerDeviceKind.invertedStylus,
+            },
+          ),
+          child: SingleChildScrollView(
+            controller: sc,
+            scrollDirection: Axis.horizontal,
+            child: Wrap(spacing: 4, children: children),
+          ),
         ),
         ),
       ),
       ),
     );
     );

+ 1 - 0
frontend/app_flowy/test/widget_test/select_option_text_field_test.dart

@@ -28,6 +28,7 @@ void main() {
         remainder = remaining;
         remainder = remaining;
         select = options;
         select = options;
       },
       },
+      onRemove: (_) {},
       newText: (text) => remainder = text,
       newText: (text) => remainder = text,
       textSeparators: const [','],
       textSeparators: const [','],
       textController: TextEditingController(),
       textController: TextEditingController(),