feat: dark mode improvement (#90)

* chore: add item pop up style and new clear icon

* fix: enable ColorPicker hover color

* fix: fix text overflow
This commit is contained in:
Yijing Huang 2023-04-20 20:57:02 -05:00 • committed by GitHub
commit a864409b6f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 49 deletions

View file

@ -1,5 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2C6.49 2 2 6.49 2 12C2 17.51 6.49 22 12 22C17.51 22 22 17.51 22 12C22 6.49 17.51 2 12 2ZM15.36 14.3C15.65 14.59 15.65 15.07 15.36 15.36C15.21 15.51 15.02 15.58 14.83 15.58C14.64 15.58 14.45 15.51 14.3 15.36L12 13.06L9.7 15.36C9.55 15.51 9.36 15.58 9.17 15.58C8.98 15.58 8.79 15.51 8.64 15.36C8.35 15.07 8.35 14.59 8.64 14.3L10.94 12L8.64 9.7C8.35 9.41 8.35 8.93 8.64 8.64C8.93 8.35 9.41 8.35 9.7 8.64L12 10.94L14.3 8.64C14.59 8.35 15.07 8.35 15.36 8.64C15.65 8.93 15.65 9.41 15.36 9.7L13.06 12L15.36 14.3Z" fill="#BDBDBD"></path> </svg>
<circle cx="8" cy="8" r="7" fill="#F2F2F2"/>
<path d="M6 6L10 10" stroke="#BDBDBD" stroke-linecap="round"/>
<path d="M10 6L6 10" stroke="#BDBDBD" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 274 B

After

Width:  |  Height:  |  Size: 649 B

Before After
Before After

View file

@ -1,4 +1,6 @@
import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/infra/flowy_svg.dart'; import 'package:appflowy_editor/src/infra/flowy_svg.dart';
import 'package:appflowy_editor/src/render/style/editor_style.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class ColorOption { class ColorOption {
@ -19,6 +21,7 @@ enum _ColorType {
class ColorPicker extends StatefulWidget { class ColorPicker extends StatefulWidget {
const ColorPicker({ const ColorPicker({
super.key, super.key,
this.editorState,
this.selectedFontColorHex, this.selectedFontColorHex,
this.selectedBackgroundColorHex, this.selectedBackgroundColorHex,
required this.pickerBackgroundColor, required this.pickerBackgroundColor,
@ -29,7 +32,7 @@ class ColorPicker extends StatefulWidget {
required this.onSubmittedbackgroundColorHex, required this.onSubmittedbackgroundColorHex,
required this.onSubmittedFontColorHex, required this.onSubmittedFontColorHex,
}); });
final EditorState? editorState;
final String? selectedFontColorHex; final String? selectedFontColorHex;
final String? selectedBackgroundColorHex; final String? selectedBackgroundColorHex;
final Color pickerBackgroundColor; final Color pickerBackgroundColor;
@ -53,6 +56,7 @@ class _ColorPickerState extends State<ColorPicker> {
TextEditingController(); TextEditingController();
final TextEditingController _backgroundColorOpacityController = final TextEditingController _backgroundColorOpacityController =
TextEditingController(); TextEditingController();
EditorStyle? get style => widget.editorState?.editorStyle;
@override @override
void initState() { void initState() {
@ -131,7 +135,6 @@ class _ColorPickerState extends State<ColorPicker> {
return Text( return Text(
text, text,
style: const TextStyle( style: const TextStyle(
color: Colors.grey,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
); );
@ -154,47 +157,48 @@ class _ColorPickerState extends State<ColorPicker> {
Widget _buildColorItem(_ColorType type, ColorOption option, bool isChecked) { Widget _buildColorItem(_ColorType type, ColorOption option, bool isChecked) {
return SizedBox( return SizedBox(
height: 36, height: 36,
child: InkWell( child: TextButton.icon(
customBorder: RoundedRectangleBorder( onPressed: () {
borderRadius: BorderRadius.circular(6),
),
hoverColor: widget.pickerItemHoverColor,
onTap: () {
if (type == _ColorType.font) { if (type == _ColorType.font) {
widget.onSubmittedFontColorHex(option.colorHex); widget.onSubmittedFontColorHex(option.colorHex);
} else if (type == _ColorType.background) { } else if (type == _ColorType.background) {
widget.onSubmittedbackgroundColorHex(option.colorHex); widget.onSubmittedbackgroundColorHex(option.colorHex);
} }
}, },
child: Row( icon: SizedBox.square(
mainAxisAlignment: MainAxisAlignment.start, dimension: 12,
mainAxisSize: MainAxisSize.min, child: Container(
children: [ decoration: BoxDecoration(
// padding color: Color(int.tryParse(option.colorHex) ?? 0xFFFFFFFF),
const SizedBox(width: 6), shape: BoxShape.circle,
// icon
SizedBox.square(
dimension: 12,
child: Container(
decoration: BoxDecoration(
color: Color(int.tryParse(option.colorHex) ?? 0xFFFFFFFF),
shape: BoxShape.circle,
),
),
), ),
// padding ),
const SizedBox(width: 10), ),
// text style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return style!.popupMenuHoverColor!;
}
return Colors.transparent;
},
),
),
label: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded( Expanded(
child: Text( child: Text(
option.name, option.name,
style: style:
TextStyle(fontSize: 12, color: widget.pickerItemTextColor), TextStyle(fontSize: 12, color: widget.pickerItemTextColor),
softWrap: false,
maxLines: 1,
overflow: TextOverflow.fade,
), ),
), ),
// checkbox // checkbox
if (isChecked) const FlowySvg(name: 'checkmark'), if (isChecked) const FlowySvg(name: 'checkmark'),
const SizedBox(width: 6),
], ],
), ),
), ),

View file

@ -77,19 +77,19 @@ class _LinkMenuState extends State<LinkMenu> {
if (widget.linkText != null) ...[ if (widget.linkText != null) ...[
_buildIconButton( _buildIconButton(
iconName: 'link', iconName: 'link',
color: style?.selectionMenuItemIconColor, color: style?.popupMenuFGColor,
text: 'Open link', text: 'Open link',
onPressed: widget.onOpenLink, onPressed: widget.onOpenLink,
), ),
_buildIconButton( _buildIconButton(
iconName: 'copy', iconName: 'copy',
color: style?.selectionMenuItemIconColor, color: style?.popupMenuFGColor,
text: 'Copy link', text: 'Copy link',
onPressed: widget.onCopyLink, onPressed: widget.onCopyLink,
), ),
_buildIconButton( _buildIconButton(
iconName: 'delete', iconName: 'delete',
color: style?.selectionMenuItemIconColor, color: style?.popupMenuFGColor,
text: 'Remove link', text: 'Remove link',
onPressed: widget.onRemoveLink, onPressed: widget.onRemoveLink,
), ),
@ -102,11 +102,10 @@ class _LinkMenuState extends State<LinkMenu> {
} }
Widget _buildHeader() { Widget _buildHeader() {
return const Text( return Text(
'Add your link', 'Add your link',
style: TextStyle( style: TextStyle(
color: Colors.grey, fontSize: style?.textStyle?.fontSize,
fontWeight: FontWeight.bold,
), ),
); );
} }
@ -114,13 +113,17 @@ class _LinkMenuState extends State<LinkMenu> {
Widget _buildInput() { Widget _buildInput() {
return TextField( return TextField(
focusNode: _focusNode, focusNode: _focusNode,
style: const TextStyle(fontSize: 14.0), style: TextStyle(
fontSize: style?.textStyle?.fontSize,
),
textAlign: TextAlign.left, textAlign: TextAlign.left,
controller: _textEditingController, controller: _textEditingController,
onSubmitted: widget.onSubmitted, onSubmitted: widget.onSubmitted,
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'URL', hintText: 'URL',
hintStyle: const TextStyle(fontSize: 14.0), hintStyle: TextStyle(
fontSize: style?.textStyle?.fontSize,
),
contentPadding: const EdgeInsets.all(16.0), contentPadding: const EdgeInsets.all(16.0),
isDense: true, isDense: true,
suffixIcon: IconButton( suffixIcon: IconButton(
@ -151,20 +154,24 @@ class _LinkMenuState extends State<LinkMenu> {
name: iconName, name: iconName,
color: color, color: color,
), ),
style: TextButton.styleFrom(
minimumSize: const Size.fromHeight(40),
padding: EdgeInsets.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
alignment: Alignment.centerLeft,
),
label: Text( label: Text(
text, text,
textAlign: TextAlign.left, textAlign: TextAlign.left,
style: TextStyle( style: TextStyle(
color: style?.selectionMenuItemTextColor ?? Colors.black, color: color,
fontSize: 14.0, fontSize: 14.0,
), ),
), ),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return style!.popupMenuHoverColor!;
}
return Colors.transparent;
},
),
),
onPressed: onPressed, onPressed: onPressed,
); );
} }

View file

@ -42,6 +42,10 @@ class EditorStyle extends ThemeExtension<EditorStyle> {
final TextStyle? code; final TextStyle? code;
final String? highlightColorHex; final String? highlightColorHex;
// Item's pop up menu styles
final Color? popupMenuFGColor;
final Color? popupMenuHoverColor;
EditorStyle({ EditorStyle({
required this.padding, required this.padding,
required this.backgroundColor, required this.backgroundColor,
@ -66,6 +70,8 @@ class EditorStyle extends ThemeExtension<EditorStyle> {
required this.code, required this.code,
required this.highlightColorHex, required this.highlightColorHex,
required this.lineHeight, required this.lineHeight,
required this.popupMenuFGColor,
required this.popupMenuHoverColor,
}); });
@override @override
@ -92,6 +98,8 @@ class EditorStyle extends ThemeExtension<EditorStyle> {
TextStyle? code, TextStyle? code,
String? highlightColorHex, String? highlightColorHex,
double? lineHeight, double? lineHeight,
Color? popupMenuFGColor,
Color? popupMenuHoverColor,
}) { }) {
return EditorStyle( return EditorStyle(
padding: padding ?? this.padding, padding: padding ?? this.padding,
@ -123,6 +131,8 @@ class EditorStyle extends ThemeExtension<EditorStyle> {
code: code ?? this.code, code: code ?? this.code,
highlightColorHex: highlightColorHex ?? this.highlightColorHex, highlightColorHex: highlightColorHex ?? this.highlightColorHex,
lineHeight: lineHeight ?? this.lineHeight, lineHeight: lineHeight ?? this.lineHeight,
popupMenuFGColor: popupMenuFGColor ?? this.popupMenuFGColor,
popupMenuHoverColor: popupMenuHoverColor ?? this.popupMenuHoverColor,
); );
} }
@ -183,6 +193,9 @@ class EditorStyle extends ThemeExtension<EditorStyle> {
code: TextStyle.lerp(code, other.code, t), code: TextStyle.lerp(code, other.code, t),
highlightColorHex: highlightColorHex, highlightColorHex: highlightColorHex,
lineHeight: lineHeight, lineHeight: lineHeight,
popupMenuFGColor: Color.lerp(popupMenuFGColor, other.popupMenuFGColor, t),
popupMenuHoverColor:
Color.lerp(popupMenuHoverColor, other.popupMenuHoverColor, t),
); );
} }
@ -223,6 +236,8 @@ class EditorStyle extends ThemeExtension<EditorStyle> {
), ),
highlightColorHex: '0x6000BCF0', highlightColorHex: '0x6000BCF0',
lineHeight: 1.5, lineHeight: 1.5,
popupMenuFGColor: const Color(0xFF333333),
popupMenuHoverColor: const Color(0xFFE0F8FF),
); );
static final dark = light.copyWith( static final dark = light.copyWith(
@ -240,5 +255,7 @@ class EditorStyle extends ThemeExtension<EditorStyle> {
selectionMenuItemSelectedColor: const Color(0xFF00BCF0), selectionMenuItemSelectedColor: const Color(0xFF00BCF0),
toolbarColor: const Color(0xFF131720), toolbarColor: const Color(0xFF131720),
toolbarElevation: 0.0, toolbarElevation: 0.0,
popupMenuFGColor: Colors.white,
popupMenuHoverColor: const Color(0xFF00BCF0),
); );
} }

View file

@ -571,10 +571,11 @@ void showColorMenu(
child: Material( child: Material(
color: Colors.transparent, color: Colors.transparent,
child: ColorPicker( child: ColorPicker(
editorState: editorState,
pickerBackgroundColor: pickerBackgroundColor:
style.selectionMenuBackgroundColor ?? Colors.white, style.selectionMenuBackgroundColor ?? Colors.white,
pickerItemHoverColor: style.selectionMenuItemSelectedColor ?? pickerItemHoverColor:
Colors.blue.withOpacity(0.3), style.popupMenuHoverColor ?? Colors.blue.withOpacity(0.3),
pickerItemTextColor: pickerItemTextColor:
style.selectionMenuItemTextColor ?? Colors.black, style.selectionMenuItemTextColor ?? Colors.black,
selectedFontColorHex: fontColorHex, selectedFontColorHex: fontColorHex,