diff --git a/frontend/app_flowy/packages/appflowy_editor/example/lib/main.dart b/frontend/app_flowy/packages/appflowy_editor/example/lib/main.dart index bef4dce946..128f227676 100644 --- a/frontend/app_flowy/packages/appflowy_editor/example/lib/main.dart +++ b/frontend/app_flowy/packages/appflowy_editor/example/lib/main.dart @@ -39,6 +39,8 @@ class MyApp extends StatelessWidget { primarySwatch: Colors.blue, // extensions: [HeadingPluginStyle.light], ), + darkTheme: ThemeData.dark(), + themeMode: ThemeMode.dark, home: const MyHomePage(title: 'AppFlowyEditor Example'), ); } diff --git a/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/code_block_node_widget.dart b/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/code_block_node_widget.dart index 6716cca163..5ecf4d4ed8 100644 --- a/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/code_block_node_widget.dart +++ b/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/code_block_node_widget.dart @@ -46,7 +46,7 @@ ShortcutEventHandler _ignorekHandler = (editorState, event) { SelectionMenuItem codeBlockMenuItem = SelectionMenuItem( name: () => 'Code Block', - icon: const Icon( + icon: (_, __) => const Icon( Icons.abc, color: Colors.black, size: 18.0, diff --git a/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/horizontal_rule_node_widget.dart b/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/horizontal_rule_node_widget.dart index c38cc0846c..0ca302de18 100644 --- a/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/horizontal_rule_node_widget.dart +++ b/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/horizontal_rule_node_widget.dart @@ -38,7 +38,7 @@ ShortcutEventHandler _insertHorzaontalRule = (editorState, event) { SelectionMenuItem horizontalRuleMenuItem = SelectionMenuItem( name: () => 'Horizontal rule', - icon: const Icon( + icon: (_, __) => const Icon( Icons.horizontal_rule, color: Colors.black, size: 18.0, diff --git a/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/tex_block_node_widget.dart b/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/tex_block_node_widget.dart index a6b958b0ed..c9b0e8d478 100644 --- a/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/tex_block_node_widget.dart +++ b/frontend/app_flowy/packages/appflowy_editor/example/lib/plugin/tex_block_node_widget.dart @@ -6,7 +6,7 @@ import 'package:flutter_math_fork/flutter_math.dart'; SelectionMenuItem teXBlockMenuItem = SelectionMenuItem( name: () => 'Tex', - icon: const Icon( + icon: (_, __) => const Icon( Icons.text_fields_rounded, color: Colors.black, size: 18.0, diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_item_widget.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_item_widget.dart index a4322c59fe..cc92b60da0 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_item_widget.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_item_widget.dart @@ -3,7 +3,7 @@ import 'package:appflowy_editor/src/render/selection_menu/selection_menu_service import 'package:appflowy_editor/src/render/selection_menu/selection_menu_widget.dart'; import 'package:flutter/material.dart'; -class SelectionMenuItemWidget extends StatelessWidget { +class SelectionMenuItemWidget extends StatefulWidget { const SelectionMenuItemWidget({ Key? key, required this.editorState, @@ -11,7 +11,6 @@ class SelectionMenuItemWidget extends StatelessWidget { required this.item, required this.isSelected, this.width = 140.0, - this.selectedColor = const Color(0xFFE0F8FF), }) : super(key: key); final EditorState editorState; @@ -19,33 +18,52 @@ class SelectionMenuItemWidget extends StatelessWidget { final SelectionMenuItem item; final double width; final bool isSelected; - final Color selectedColor; + + @override + State createState() => + _SelectionMenuItemWidgetState(); +} + +class _SelectionMenuItemWidgetState extends State { + var _onHover = false; @override Widget build(BuildContext context) { + final editorStyle = widget.editorState.editorStyle; return Container( padding: const EdgeInsets.fromLTRB(8.0, 5.0, 8.0, 5.0), child: SizedBox( - width: width, + width: widget.width, child: TextButton.icon( - icon: item.icon, + icon: widget.item + .icon(widget.editorState, widget.isSelected || _onHover), style: ButtonStyle( alignment: Alignment.centerLeft, - overlayColor: MaterialStateProperty.all(selectedColor), - backgroundColor: isSelected - ? MaterialStateProperty.all(selectedColor) + overlayColor: MaterialStateProperty.all( + editorStyle.selectionMenuItemSelectedColor), + backgroundColor: widget.isSelected + ? MaterialStateProperty.all( + editorStyle.selectionMenuItemSelectedColor) : MaterialStateProperty.all(Colors.transparent), ), label: Text( - item.name(), + widget.item.name(), textAlign: TextAlign.left, - style: const TextStyle( - color: Colors.black, - fontSize: 14.0, + style: TextStyle( + color: widget.isSelected || _onHover + ? editorStyle.selectionMenuItemSelectedTextColor + : editorStyle.selectionMenuItemTextColor, + fontSize: 12.0, ), ), onPressed: () { - item.handler(editorState, menuService, context); + widget.item + .handler(widget.editorState, widget.menuService, context); + }, + onHover: (value) { + setState(() { + _onHover = value; + }); }, ), ), diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_service.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_service.dart index c36b9adb8e..1f47ad823b 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_service.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_service.dart @@ -131,7 +131,8 @@ List get defaultSelectionMenuItems => final List _defaultSelectionMenuItems = [ SelectionMenuItem( name: () => AppFlowyEditorLocalizations.current.text, - icon: _selectionMenuIcon('text'), + icon: (editorState, onSelected) => + _selectionMenuIcon('text', editorState, onSelected), keywords: ['text'], handler: (editorState, _, __) { insertTextNodeAfterSelection(editorState, {}); @@ -139,7 +140,8 @@ final List _defaultSelectionMenuItems = [ ), SelectionMenuItem( name: () => AppFlowyEditorLocalizations.current.heading1, - icon: _selectionMenuIcon('h1'), + icon: (editorState, onSelected) => + _selectionMenuIcon('h1', editorState, onSelected), keywords: ['heading 1, h1'], handler: (editorState, _, __) { insertHeadingAfterSelection(editorState, BuiltInAttributeKey.h1); @@ -147,7 +149,8 @@ final List _defaultSelectionMenuItems = [ ), SelectionMenuItem( name: () => AppFlowyEditorLocalizations.current.heading2, - icon: _selectionMenuIcon('h2'), + icon: (editorState, onSelected) => + _selectionMenuIcon('h2', editorState, onSelected), keywords: ['heading 2, h2'], handler: (editorState, _, __) { insertHeadingAfterSelection(editorState, BuiltInAttributeKey.h2); @@ -155,7 +158,8 @@ final List _defaultSelectionMenuItems = [ ), SelectionMenuItem( name: () => AppFlowyEditorLocalizations.current.heading3, - icon: _selectionMenuIcon('h3'), + icon: (editorState, onSelected) => + _selectionMenuIcon('h3', editorState, onSelected), keywords: ['heading 3, h3'], handler: (editorState, _, __) { insertHeadingAfterSelection(editorState, BuiltInAttributeKey.h3); @@ -163,13 +167,15 @@ final List _defaultSelectionMenuItems = [ ), SelectionMenuItem( name: () => AppFlowyEditorLocalizations.current.image, - icon: _selectionMenuIcon('image'), + icon: (editorState, onSelected) => + _selectionMenuIcon('image', editorState, onSelected), keywords: ['image'], handler: showImageUploadMenu, ), SelectionMenuItem( name: () => AppFlowyEditorLocalizations.current.bulletedList, - icon: _selectionMenuIcon('bulleted_list'), + icon: (editorState, onSelected) => + _selectionMenuIcon('bulleted_list', editorState, onSelected), keywords: ['bulleted list', 'list', 'unordered list'], handler: (editorState, _, __) { insertBulletedListAfterSelection(editorState); @@ -177,7 +183,8 @@ final List _defaultSelectionMenuItems = [ ), SelectionMenuItem( name: () => AppFlowyEditorLocalizations.current.numberedList, - icon: _selectionMenuIcon('number'), + icon: (editorState, onSelected) => + _selectionMenuIcon('number', editorState, onSelected), keywords: ['numbered list', 'list', 'ordered list'], handler: (editorState, _, __) { insertNumberedListAfterSelection(editorState); @@ -185,7 +192,8 @@ final List _defaultSelectionMenuItems = [ ), SelectionMenuItem( name: () => AppFlowyEditorLocalizations.current.checkbox, - icon: _selectionMenuIcon('checkbox'), + icon: (editorState, onSelected) => + _selectionMenuIcon('checkbox', editorState, onSelected), keywords: ['todo list', 'list', 'checkbox list'], handler: (editorState, _, __) { insertCheckboxAfterSelection(editorState); @@ -193,7 +201,8 @@ final List _defaultSelectionMenuItems = [ ), SelectionMenuItem( name: () => AppFlowyEditorLocalizations.current.quote, - icon: _selectionMenuIcon('quote'), + icon: (editorState, onSelected) => + _selectionMenuIcon('quote', editorState, onSelected), keywords: ['quote', 'refer'], handler: (editorState, _, __) { insertQuoteAfterSelection(editorState); @@ -201,10 +210,13 @@ final List _defaultSelectionMenuItems = [ ), ]; -Widget _selectionMenuIcon(String name) { +Widget _selectionMenuIcon( + String name, EditorState editorState, bool onSelected) { return FlowySvg( name: 'selection_menu/$name', - color: Colors.black, + color: onSelected + ? editorState.editorStyle.selectionMenuItemSelectedIconColor + : editorState.editorStyle.selectionMenuItemIconColor, width: 18.0, height: 18.0, ); diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_widget.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_widget.dart index 2f64e8a4a6..2007c172f5 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_widget.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/selection_menu/selection_menu_widget.dart @@ -29,7 +29,7 @@ class SelectionMenuItem { } final String Function() name; - final Widget icon; + final Widget Function(EditorState editorState, bool onSelected) icon; /// Customizes keywords for item. /// @@ -142,7 +142,7 @@ class _SelectionMenuWidgetState extends State { onKey: _onKey, child: Container( decoration: BoxDecoration( - color: Colors.white, + color: widget.editorState.editorStyle.selectionMenuBackgroundColor, boxShadow: [ BoxShadow( blurRadius: 5, diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/style/editor_style.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/style/editor_style.dart index 47d64ac373..892c274474 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/style/editor_style.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/style/editor_style.dart @@ -14,6 +14,14 @@ class EditorStyle extends ThemeExtension { final Color? cursorColor; final Color? selectionColor; + // Selection menu styles + final Color? selectionMenuBackgroundColor; + final Color? selectionMenuItemTextColor; + final Color? selectionMenuItemIconColor; + final Color? selectionMenuItemSelectedTextColor; + final Color? selectionMenuItemSelectedIconColor; + final Color? selectionMenuItemSelectedColor; + // Text styles final EdgeInsets? textPadding; final TextStyle? textStyle; @@ -33,6 +41,12 @@ class EditorStyle extends ThemeExtension { required this.padding, required this.cursorColor, required this.selectionColor, + required this.selectionMenuBackgroundColor, + required this.selectionMenuItemTextColor, + required this.selectionMenuItemIconColor, + required this.selectionMenuItemSelectedTextColor, + required this.selectionMenuItemSelectedIconColor, + required this.selectionMenuItemSelectedColor, required this.textPadding, required this.textStyle, required this.placeholderTextStyle, @@ -51,6 +65,12 @@ class EditorStyle extends ThemeExtension { EdgeInsets? padding, Color? cursorColor, Color? selectionColor, + Color? selectionMenuBackgroundColor, + Color? selectionMenuItemTextColor, + Color? selectionMenuItemIconColor, + Color? selectionMenuItemSelectedTextColor, + Color? selectionMenuItemSelectedIconColor, + Color? selectionMenuItemSelectedColor, TextStyle? textStyle, TextStyle? placeholderTextStyle, TextStyle? bold, @@ -66,6 +86,18 @@ class EditorStyle extends ThemeExtension { padding: padding ?? this.padding, cursorColor: cursorColor ?? this.cursorColor, selectionColor: selectionColor ?? this.selectionColor, + selectionMenuBackgroundColor: + selectionMenuBackgroundColor ?? this.selectionMenuBackgroundColor, + selectionMenuItemTextColor: + selectionMenuItemTextColor ?? this.selectionMenuItemTextColor, + selectionMenuItemIconColor: + selectionMenuItemIconColor ?? this.selectionMenuItemIconColor, + selectionMenuItemSelectedTextColor: selectionMenuItemSelectedTextColor ?? + selectionMenuItemSelectedTextColor, + selectionMenuItemSelectedIconColor: selectionMenuItemSelectedIconColor ?? + selectionMenuItemSelectedIconColor, + selectionMenuItemSelectedColor: + selectionMenuItemSelectedColor ?? this.selectionMenuItemSelectedColor, textPadding: textPadding ?? textPadding, textStyle: textStyle ?? this.textStyle, placeholderTextStyle: placeholderTextStyle ?? this.placeholderTextStyle, @@ -91,6 +123,22 @@ class EditorStyle extends ThemeExtension { cursorColor: Color.lerp(cursorColor, other.cursorColor, t), textPadding: EdgeInsets.lerp(textPadding, other.textPadding, t), selectionColor: Color.lerp(selectionColor, other.selectionColor, t), + selectionMenuBackgroundColor: Color.lerp( + selectionMenuBackgroundColor, other.selectionMenuBackgroundColor, t), + selectionMenuItemTextColor: Color.lerp( + selectionMenuItemTextColor, other.selectionMenuItemTextColor, t), + selectionMenuItemIconColor: Color.lerp( + selectionMenuItemIconColor, other.selectionMenuItemIconColor, t), + selectionMenuItemSelectedTextColor: Color.lerp( + selectionMenuItemSelectedTextColor, + other.selectionMenuItemSelectedTextColor, + t), + selectionMenuItemSelectedIconColor: Color.lerp( + selectionMenuItemSelectedIconColor, + other.selectionMenuItemSelectedIconColor, + t), + selectionMenuItemSelectedColor: Color.lerp(selectionMenuItemSelectedColor, + other.selectionMenuItemSelectedColor, t), textStyle: TextStyle.lerp(textStyle, other.textStyle, t), placeholderTextStyle: TextStyle.lerp(placeholderTextStyle, other.placeholderTextStyle, t), @@ -109,6 +157,12 @@ class EditorStyle extends ThemeExtension { padding: const EdgeInsets.fromLTRB(200.0, 0.0, 200.0, 0.0), cursorColor: const Color(0xFF00BCF0), selectionColor: const Color.fromARGB(53, 111, 201, 231), + selectionMenuBackgroundColor: const Color(0xFFFFFFFF), + selectionMenuItemTextColor: const Color(0xFF333333), + selectionMenuItemIconColor: const Color(0xFF333333), + selectionMenuItemSelectedTextColor: const Color(0xFF333333), + selectionMenuItemSelectedIconColor: const Color(0xFF333333), + selectionMenuItemSelectedColor: const Color(0xFFE0F8FF), textPadding: const EdgeInsets.symmetric(vertical: 8.0), textStyle: const TextStyle(fontSize: 16.0, color: Colors.black), placeholderTextStyle: const TextStyle(fontSize: 16.0, color: Colors.grey), @@ -135,5 +189,11 @@ class EditorStyle extends ThemeExtension { fontSize: 16.0, color: Colors.white.withOpacity(0.3), ), + selectionMenuBackgroundColor: const Color(0xFF282E3A), + selectionMenuItemTextColor: const Color(0xFFBBC3CD), + selectionMenuItemIconColor: const Color(0xFFBBC3CD), + selectionMenuItemSelectedTextColor: const Color(0xFF131720), + selectionMenuItemSelectedIconColor: const Color(0xFF131720), + selectionMenuItemSelectedColor: const Color(0xFF00BCF0), ); } diff --git a/frontend/app_flowy/packages/appflowy_editor/test/render/selection_menu/selection_menu_widget_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/render/selection_menu/selection_menu_widget_test.dart index f60d1610ad..d058fc2199 100644 --- a/frontend/app_flowy/packages/appflowy_editor/test/render/selection_menu/selection_menu_widget_test.dart +++ b/frontend/app_flowy/packages/appflowy_editor/test/render/selection_menu/selection_menu_widget_test.dart @@ -137,7 +137,7 @@ Future _prepare(WidgetTester tester) async { ); for (final item in defaultSelectionMenuItems) { - expect(find.byWidget(item.icon), findsOneWidget); + expect(find.text(item.name()), findsOneWidget); } return Future.value(editor); diff --git a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/slash_handler_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/slash_handler_test.dart index b3166a46fb..0b53b43af9 100644 --- a/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/slash_handler_test.dart +++ b/frontend/app_flowy/packages/appflowy_editor/test/service/internal_key_event_handlers/slash_handler_test.dart @@ -30,7 +30,7 @@ void main() async { ); for (final item in defaultSelectionMenuItems) { - expect(find.byWidget(item.icon), findsOneWidget); + expect(find.text(item.name()), findsOneWidget); } await editor.updateSelection(Selection.single(path: [1], startOffset: 0));