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:
parent
0f303cbd8e
commit
a864409b6f
5 changed files with 74 additions and 49 deletions
|
|
@ -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 |
|
|
@ -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),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue