feat: customize desktop toolbar style (#519)
This commit is contained in:
parent
8bfd779bfe
commit
5155663163
17 changed files with 56 additions and 17 deletions
|
|
@ -7,10 +7,16 @@ class FloatingToolbarStyle {
|
|||
const FloatingToolbarStyle({
|
||||
this.backgroundColor = Colors.black,
|
||||
this.toolbarActiveColor = Colors.lightBlue,
|
||||
this.toolbarIconColor = Colors.white,
|
||||
this.toolbarShadowColor,
|
||||
this.toolbarElevation = 0,
|
||||
});
|
||||
|
||||
final Color backgroundColor;
|
||||
final Color toolbarActiveColor;
|
||||
final Color toolbarIconColor;
|
||||
final Color? toolbarShadowColor;
|
||||
final double toolbarElevation;
|
||||
}
|
||||
|
||||
/// A floating toolbar that displays at the top of the editor when the selection
|
||||
|
|
@ -124,6 +130,7 @@ class _FloatingToolbarState extends State<FloatingToolbar>
|
|||
}
|
||||
|
||||
final String _debounceKey = 'show the toolbar';
|
||||
|
||||
void _clear() {
|
||||
Debounce.cancel(_debounceKey);
|
||||
|
||||
|
|
@ -181,6 +188,9 @@ class _FloatingToolbarState extends State<FloatingToolbar>
|
|||
editorState: editorState,
|
||||
backgroundColor: widget.style.backgroundColor,
|
||||
toolbarActiveColor: widget.style.toolbarActiveColor,
|
||||
toolbarIconColor: widget.style.toolbarIconColor,
|
||||
toolbarElevation: widget.style.toolbarElevation,
|
||||
toolbarShadowColor: widget.style.toolbarShadowColor,
|
||||
textDirection: widget.textDirection ?? Directionality.of(context),
|
||||
);
|
||||
return _toolbarWidget!;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ class FloatingToolbarWidget extends StatefulWidget {
|
|||
super.key,
|
||||
this.backgroundColor = Colors.black,
|
||||
required this.toolbarActiveColor,
|
||||
this.toolbarIconColor,
|
||||
this.toolbarElevation = 0,
|
||||
this.toolbarShadowColor,
|
||||
required this.items,
|
||||
required this.editorState,
|
||||
required this.textDirection,
|
||||
|
|
@ -23,6 +26,9 @@ class FloatingToolbarWidget extends StatefulWidget {
|
|||
final List<ToolbarItem> items;
|
||||
final Color backgroundColor;
|
||||
final Color toolbarActiveColor;
|
||||
final Color? toolbarIconColor;
|
||||
final double toolbarElevation;
|
||||
final Color? toolbarShadowColor;
|
||||
final EditorState editorState;
|
||||
final TextDirection textDirection;
|
||||
|
||||
|
|
@ -40,6 +46,8 @@ class _FloatingToolbarWidgetState extends State<FloatingToolbarWidget> {
|
|||
return Material(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
color: widget.backgroundColor,
|
||||
shadowColor: widget.toolbarShadowColor,
|
||||
elevation: widget.toolbarElevation,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: SizedBox(
|
||||
|
|
@ -59,6 +67,7 @@ class _FloatingToolbarWidgetState extends State<FloatingToolbarWidget> {
|
|||
context,
|
||||
widget.editorState,
|
||||
widget.toolbarActiveColor,
|
||||
widget.toolbarIconColor,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class _AlignmentToolbarItem extends ToolbarItem {
|
|||
id: 'editor.$id',
|
||||
group: 6,
|
||||
isActive: onlyShowInTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
final selection = editorState.selection!;
|
||||
final nodes = editorState.getNodesInSelection(selection);
|
||||
final isHighlight = nodes.every(
|
||||
|
|
@ -42,6 +42,7 @@ class _AlignmentToolbarItem extends ToolbarItem {
|
|||
iconName: 'toolbar/$name',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: tooltip,
|
||||
onPressed: () => editorState.updateNode(
|
||||
selection,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ final ToolbarItem bulletedListItem = ToolbarItem(
|
|||
id: 'editor.bulleted_list',
|
||||
group: 3,
|
||||
isActive: onlyShowInSingleSelectionAndTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
final selection = editorState.selection!;
|
||||
final node = editorState.getNodeAtPath(selection.start.path)!;
|
||||
final isHighlight = node.type == 'bulleted_list';
|
||||
|
|
@ -12,6 +12,7 @@ final ToolbarItem bulletedListItem = ToolbarItem(
|
|||
iconName: 'toolbar/bulleted_list',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: AppFlowyEditorLocalizations.current.bulletedList,
|
||||
onPressed: () => editorState.formatNode(
|
||||
selection,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ ToolbarItem buildHighlightColorItem({List<ColorOption>? colorOptions}) {
|
|||
id: 'editor.highlightColor',
|
||||
group: 4,
|
||||
isActive: onlyShowInTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
String? highlightColorHex;
|
||||
|
||||
final selection = editorState.selection!;
|
||||
|
|
@ -20,6 +20,7 @@ ToolbarItem buildHighlightColorItem({List<ColorOption>? colorOptions}) {
|
|||
iconName: 'toolbar/highlight_color',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: AppFlowyEditorLocalizations.current.highlightColor,
|
||||
onPressed: () {
|
||||
bool showClearButton = false;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ ToolbarItem buildTextColorItem({
|
|||
id: 'editor.textColor',
|
||||
group: 4,
|
||||
isActive: onlyShowInTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
String? textColorHex;
|
||||
final selection = editorState.selection!;
|
||||
final nodes = editorState.getNodesInSelection(selection);
|
||||
|
|
@ -21,6 +21,7 @@ ToolbarItem buildTextColorItem({
|
|||
iconName: 'toolbar/text_color',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: AppFlowyEditorLocalizations.current.textColor,
|
||||
onPressed: () {
|
||||
bool showClearButton = false;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class _FormatToolbarItem extends ToolbarItem {
|
|||
id: 'editor.$id',
|
||||
group: 2,
|
||||
isActive: onlyShowInTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
final selection = editorState.selection!;
|
||||
final nodes = editorState.getNodesInSelection(selection);
|
||||
final isHighlight = nodes.allSatisfyInSelection(selection, (delta) {
|
||||
|
|
@ -55,6 +55,7 @@ class _FormatToolbarItem extends ToolbarItem {
|
|||
iconName: 'toolbar/$name',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: tooltip,
|
||||
onPressed: () => editorState.toggleAttribute(name),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class _HeadingToolbarItem extends ToolbarItem {
|
|||
id: 'editor.h$level',
|
||||
group: 1,
|
||||
isActive: onlyShowInSingleSelectionAndTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
final selection = editorState.selection!;
|
||||
final node = editorState.getNodeAtPath(selection.start.path)!;
|
||||
final isHighlight =
|
||||
|
|
@ -22,6 +22,7 @@ class _HeadingToolbarItem extends ToolbarItem {
|
|||
iconName: 'toolbar/h$level',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: levelToTooltips(level),
|
||||
onPressed: () => editorState.formatNode(
|
||||
selection,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ class SVGIconItemWidget extends StatelessWidget {
|
|||
this.iconBuilder,
|
||||
required this.isHighlight,
|
||||
required this.highlightColor,
|
||||
this.iconColor,
|
||||
this.tooltip,
|
||||
this.onPressed,
|
||||
});
|
||||
|
|
@ -20,6 +21,7 @@ class SVGIconItemWidget extends StatelessWidget {
|
|||
final WidgetBuilder? iconBuilder;
|
||||
final bool isHighlight;
|
||||
final Color highlightColor;
|
||||
final Color? iconColor;
|
||||
final String? tooltip;
|
||||
final VoidCallback? onPressed;
|
||||
|
||||
|
|
@ -29,7 +31,7 @@ class SVGIconItemWidget extends StatelessWidget {
|
|||
? iconBuilder!(context)
|
||||
: EditorSvg(
|
||||
name: iconName,
|
||||
color: isHighlight ? highlightColor : null,
|
||||
color: isHighlight ? highlightColor : iconColor,
|
||||
width: iconSize.width,
|
||||
height: iconSize.height,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ final linkItem = ToolbarItem(
|
|||
id: 'editor.link',
|
||||
group: 4,
|
||||
isActive: onlyShowInSingleSelectionAndTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
final selection = editorState.selection!;
|
||||
final nodes = editorState.getNodesInSelection(selection);
|
||||
final isHref = nodes.allSatisfyInSelection(selection, (delta) {
|
||||
|
|
@ -23,6 +23,7 @@ final linkItem = ToolbarItem(
|
|||
iconName: 'toolbar/link',
|
||||
isHighlight: isHref,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: AppFlowyEditorLocalizations.current.link,
|
||||
onPressed: () {
|
||||
showLinkMenu(context, editorState, selection, isHref);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ final ToolbarItem numberedListItem = ToolbarItem(
|
|||
id: 'editor.numbered_list',
|
||||
group: 3,
|
||||
isActive: onlyShowInSingleSelectionAndTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
final selection = editorState.selection!;
|
||||
final node = editorState.getNodeAtPath(selection.start.path)!;
|
||||
final isHighlight = node.type == 'numbered_list';
|
||||
|
|
@ -12,6 +12,7 @@ final ToolbarItem numberedListItem = ToolbarItem(
|
|||
iconName: 'toolbar/numbered_list',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: AppFlowyEditorLocalizations.current.numberedList,
|
||||
onPressed: () => editorState.formatNode(
|
||||
selection,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ final ToolbarItem paragraphItem = ToolbarItem(
|
|||
id: 'editor.paragraph',
|
||||
group: 1,
|
||||
isActive: onlyShowInSingleSelectionAndTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
final selection = editorState.selection!;
|
||||
final node = editorState.getNodeAtPath(selection.start.path)!;
|
||||
final isHighlight = node.type == 'paragraph';
|
||||
|
|
@ -13,6 +13,7 @@ final ToolbarItem paragraphItem = ToolbarItem(
|
|||
iconName: 'toolbar/text',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: AppFlowyEditorLocalizations.current.text,
|
||||
onPressed: () => editorState.formatNode(
|
||||
selection,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ final ToolbarItem placeholderItem = ToolbarItem(
|
|||
id: placeholderItemId,
|
||||
group: -1,
|
||||
isActive: (editorState) => true,
|
||||
builder: (_, __, ___) {
|
||||
builder: (_, __, ___, ____) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 5),
|
||||
child: Container(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ final ToolbarItem quoteItem = ToolbarItem(
|
|||
id: 'editor.quote',
|
||||
group: 3,
|
||||
isActive: onlyShowInSingleSelectionAndTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
final selection = editorState.selection!;
|
||||
final node = editorState.getNodeAtPath(selection.start.path)!;
|
||||
final isHighlight = node.type == 'quote';
|
||||
|
|
@ -12,6 +12,7 @@ final ToolbarItem quoteItem = ToolbarItem(
|
|||
iconName: 'toolbar/quote',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: AppFlowyEditorLocalizations.current.quote,
|
||||
onPressed: () => editorState.formatNode(
|
||||
selection,
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class _TextDirectionToolbarItem extends ToolbarItem {
|
|||
id: 'editor.$id',
|
||||
group: 7,
|
||||
isActive: onlyShowInTextType,
|
||||
builder: (context, editorState, highlightColor) {
|
||||
builder: (context, editorState, highlightColor, iconColor) {
|
||||
final selection = editorState.selection!;
|
||||
final nodes = editorState.getNodesInSelection(selection);
|
||||
final isHighlight = nodes.every(
|
||||
|
|
@ -41,6 +41,7 @@ class _TextDirectionToolbarItem extends ToolbarItem {
|
|||
iconName: 'toolbar/$iconName',
|
||||
isHighlight: isHighlight,
|
||||
highlightColor: highlightColor,
|
||||
iconColor: iconColor,
|
||||
tooltip: tooltip,
|
||||
onPressed: () => editorState.updateNode(
|
||||
selection,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class ToolbarItem {
|
|||
BuildContext context,
|
||||
EditorState editorState,
|
||||
Color highlightColor,
|
||||
Color? iconColor,
|
||||
)? builder;
|
||||
|
||||
// deprecated
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import 'package:appflowy_editor/src/editor_state.dart';
|
||||
import 'package:appflowy_editor/src/flutter/overlay.dart';
|
||||
import 'package:appflowy_editor/src/render/toolbar/toolbar_item.dart';
|
||||
import 'package:appflowy_editor/src/render/toolbar/toolbar_item_widget.dart';
|
||||
import 'package:flutter/material.dart' hide Overlay, OverlayEntry;
|
||||
|
||||
import 'package:appflowy_editor/src/editor_state.dart';
|
||||
|
||||
mixin ToolbarMixin<T extends StatefulWidget> on State<T> {
|
||||
void hide();
|
||||
}
|
||||
|
|
@ -16,6 +15,7 @@ class ToolbarWidget extends StatefulWidget {
|
|||
required this.layerLink,
|
||||
required this.offset,
|
||||
required this.highlightColor,
|
||||
this.iconColor,
|
||||
required this.items,
|
||||
this.alignment = Alignment.topLeft,
|
||||
}) : super(key: key);
|
||||
|
|
@ -24,6 +24,7 @@ class ToolbarWidget extends StatefulWidget {
|
|||
final LayerLink layerLink;
|
||||
final Offset offset;
|
||||
final Color highlightColor;
|
||||
final Color? iconColor;
|
||||
|
||||
final List<ToolbarItem> items;
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ class _ToolbarWidgetState extends State<ToolbarWidget> with ToolbarMixin {
|
|||
showWhenUnlinked: true,
|
||||
offset: widget.offset,
|
||||
followerAnchor: widget.alignment,
|
||||
child: _buildToolbar(context, widget.highlightColor),
|
||||
child: _buildToolbar(context, widget.highlightColor, widget.iconColor),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -57,7 +58,11 @@ class _ToolbarWidgetState extends State<ToolbarWidget> with ToolbarMixin {
|
|||
_listToolbarOverlay = null;
|
||||
}
|
||||
|
||||
Widget _buildToolbar(BuildContext context, Color highlightColor) {
|
||||
Widget _buildToolbar(
|
||||
BuildContext context,
|
||||
Color highlightColor,
|
||||
Color? iconColor,
|
||||
) {
|
||||
return Material(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
child: Padding(
|
||||
|
|
@ -73,6 +78,7 @@ class _ToolbarWidgetState extends State<ToolbarWidget> with ToolbarMixin {
|
|||
context,
|
||||
widget.editorState,
|
||||
highlightColor,
|
||||
iconColor,
|
||||
) ??
|
||||
item.itemBuilder?.call(context, widget.editorState) ??
|
||||
ToolbarItemWidget(
|
||||
|
|
|
|||
Loading…
Reference in a new issue