feat: improve hover color in dark mode (#5538)

This commit is contained in:
Lucas.Xu 2024-06-14 14:31:55 +08:00 committed by GitHub
parent cbe452a73d
commit 2a4d78b688
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 101 additions and 58 deletions

View File

@ -15,6 +15,7 @@ import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/sidebar_
import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart'; import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -75,6 +76,8 @@ class _Space extends StatefulWidget {
class _SpaceState extends State<_Space> { class _SpaceState extends State<_Space> {
final ValueNotifier<bool> isHovered = ValueNotifier(false); final ValueNotifier<bool> isHovered = ValueNotifier(false);
final PropertyValueNotifier<bool> isExpandedNotifier =
PropertyValueNotifier(false);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -93,12 +96,14 @@ class _SpaceState extends State<_Space> {
space: currentSpace, space: currentSpace,
onAdded: () => _showCreatePagePopup(context, currentSpace), onAdded: () => _showCreatePagePopup(context, currentSpace),
onCreateNewSpace: () => _showCreateSpaceDialog(context), onCreateNewSpace: () => _showCreateSpaceDialog(context),
onCollapseAllPages: () => isExpandedNotifier.value = true,
), ),
MouseRegion( MouseRegion(
onEnter: (_) => isHovered.value = true, onEnter: (_) => isHovered.value = true,
onExit: (_) => isHovered.value = false, onExit: (_) => isHovered.value = false,
child: _Pages( child: _Pages(
key: ValueKey(currentSpace.id), key: ValueKey(currentSpace.id),
isExpandedNotifier: isExpandedNotifier,
space: currentSpace, space: currentSpace,
isHovered: isHovered, isHovered: isHovered,
), ),
@ -156,10 +161,12 @@ class _Pages extends StatelessWidget {
super.key, super.key,
required this.space, required this.space,
required this.isHovered, required this.isHovered,
required this.isExpandedNotifier,
}); });
final ViewPB space; final ViewPB space;
final ValueNotifier<bool> isHovered; final ValueNotifier<bool> isHovered;
final PropertyValueNotifier<bool> isExpandedNotifier;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -183,6 +190,7 @@ class _Pages extends StatelessWidget {
leftPadding: HomeSpaceViewSizes.leftPadding, leftPadding: HomeSpaceViewSizes.leftPadding,
isFeedback: false, isFeedback: false,
isHovered: isHovered, isHovered: isHovered,
isExpandedNotifier: isExpandedNotifier,
onSelected: (viewContext, view) { onSelected: (viewContext, view) {
if (HardwareKeyboard.instance.isControlPressed) { if (HardwareKeyboard.instance.isControlPressed) {
context.read<TabsBloc>().openTab(view); context.read<TabsBloc>().openTab(view);

View File

@ -22,12 +22,14 @@ class SidebarSpaceHeader extends StatefulWidget {
required this.space, required this.space,
required this.onAdded, required this.onAdded,
required this.onCreateNewSpace, required this.onCreateNewSpace,
required this.onCollapseAllPages,
required this.isExpanded, required this.isExpanded,
}); });
final ViewPB space; final ViewPB space;
final VoidCallback onAdded; final VoidCallback onAdded;
final VoidCallback onCreateNewSpace; final VoidCallback onCreateNewSpace;
final VoidCallback onCollapseAllPages;
final bool isExpanded; final bool isExpanded;
@override @override
@ -156,6 +158,7 @@ class _SidebarSpaceHeaderState extends State<SidebarSpaceHeader> {
widget.onCreateNewSpace(); widget.onCreateNewSpace();
break; break;
case SpaceMoreActionType.collapseAllPages: case SpaceMoreActionType.collapseAllPages:
widget.onCollapseAllPages();
break; break;
case SpaceMoreActionType.delete: case SpaceMoreActionType.delete:
_showDeleteSpaceDialog(context); _showDeleteSpaceDialog(context);

View File

@ -71,6 +71,7 @@ class SpaceMorePopup extends StatelessWidget {
SpaceMoreActionType.manage, SpaceMoreActionType.manage,
SpaceMoreActionType.divider, SpaceMoreActionType.divider,
SpaceMoreActionType.addNewSpace, SpaceMoreActionType.addNewSpace,
SpaceMoreActionType.collapseAllPages,
SpaceMoreActionType.divider, SpaceMoreActionType.divider,
SpaceMoreActionType.delete, SpaceMoreActionType.delete,
]; ];
@ -155,7 +156,7 @@ class SpaceMoreActionTypeWrapper extends CustomActionCell {
height: 34, height: 34,
padding: const EdgeInsets.symmetric(vertical: 2.0), padding: const EdgeInsets.symmetric(vertical: 2.0),
child: Opacity( child: Opacity(
opacity: disable ? 0.5 : 1.0, opacity: disable ? 0.3 : 1.0,
child: FlowyButton( child: FlowyButton(
disable: disable, disable: disable,
margin: const EdgeInsets.symmetric(horizontal: 6), margin: const EdgeInsets.symmetric(horizontal: 6),

View File

@ -19,6 +19,7 @@ import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
import 'package:appflowy/workspace/presentation/widgets/rename_view_popover.dart'; import 'package:appflowy/workspace/presentation/widgets/rename_view_popover.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@ -58,6 +59,7 @@ class ViewItem extends StatelessWidget {
this.leftIconBuilder, this.leftIconBuilder,
this.rightIconsBuilder, this.rightIconsBuilder,
this.shouldLoadChildViews = true, this.shouldLoadChildViews = true,
this.isExpandedNotifier,
}); });
final ViewPB view; final ViewPB view;
@ -109,6 +111,7 @@ class ViewItem extends StatelessWidget {
final ViewItemRightIconsBuilder? rightIconsBuilder; final ViewItemRightIconsBuilder? rightIconsBuilder;
final bool shouldLoadChildViews; final bool shouldLoadChildViews;
final PropertyValueNotifier<bool>? isExpandedNotifier;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -144,6 +147,7 @@ class ViewItem extends StatelessWidget {
shouldRenderChildren: shouldRenderChildren, shouldRenderChildren: shouldRenderChildren,
leftIconBuilder: leftIconBuilder, leftIconBuilder: leftIconBuilder,
rightIconsBuilder: rightIconsBuilder, rightIconsBuilder: rightIconsBuilder,
isExpandedNotifier: isExpandedNotifier,
); );
}, },
), ),
@ -153,7 +157,7 @@ class ViewItem extends StatelessWidget {
bool _isDragging = false; bool _isDragging = false;
class InnerViewItem extends StatelessWidget { class InnerViewItem extends StatefulWidget {
const InnerViewItem({ const InnerViewItem({
super.key, super.key,
required this.view, required this.view,
@ -176,6 +180,7 @@ class InnerViewItem extends StatelessWidget {
this.shouldRenderChildren = true, this.shouldRenderChildren = true,
required this.leftIconBuilder, required this.leftIconBuilder,
required this.rightIconsBuilder, required this.rightIconsBuilder,
this.isExpandedNotifier,
}); });
final ViewPB view; final ViewPB view;
@ -204,46 +209,67 @@ class InnerViewItem extends StatelessWidget {
final ViewItemLeftIconBuilder? leftIconBuilder; final ViewItemLeftIconBuilder? leftIconBuilder;
final ViewItemRightIconsBuilder? rightIconsBuilder; final ViewItemRightIconsBuilder? rightIconsBuilder;
final PropertyValueNotifier<bool>? isExpandedNotifier;
@override
State<InnerViewItem> createState() => _InnerViewItemState();
}
class _InnerViewItemState extends State<InnerViewItem> {
@override
void initState() {
super.initState();
widget.isExpandedNotifier?.addListener(_collapseAllPages);
}
@override
void dispose() {
widget.isExpandedNotifier?.removeListener(_collapseAllPages);
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget child = SingleInnerViewItem( Widget child = SingleInnerViewItem(
view: view, view: widget.view,
parentView: parentView, parentView: widget.parentView,
level: level, level: widget.level,
showActions: showActions, showActions: widget.showActions,
spaceType: spaceType, spaceType: widget.spaceType,
onSelected: onSelected, onSelected: widget.onSelected,
onTertiarySelected: onTertiarySelected, onTertiarySelected: widget.onTertiarySelected,
isExpanded: isExpanded, isExpanded: widget.isExpanded,
isDraggable: isDraggable, isDraggable: widget.isDraggable,
leftPadding: leftPadding, leftPadding: widget.leftPadding,
isFeedback: isFeedback, isFeedback: widget.isFeedback,
height: height, height: widget.height,
isPlaceholder: isPlaceholder, isPlaceholder: widget.isPlaceholder,
isHovered: isHovered, isHovered: widget.isHovered,
leftIconBuilder: leftIconBuilder, leftIconBuilder: widget.leftIconBuilder,
rightIconsBuilder: rightIconsBuilder, rightIconsBuilder: widget.rightIconsBuilder,
); );
// if the view is expanded and has child views, render its child views // if the view is expanded and has child views, render its child views
if (isExpanded && shouldRenderChildren && childViews.isNotEmpty) { if (widget.isExpanded &&
final children = childViews.map((childView) { widget.shouldRenderChildren &&
widget.childViews.isNotEmpty) {
final children = widget.childViews.map((childView) {
return ViewItem( return ViewItem(
key: ValueKey('${spaceType.name} ${childView.id}'), key: ValueKey('${widget.spaceType.name} ${childView.id}'),
parentView: view, parentView: widget.view,
spaceType: spaceType, spaceType: widget.spaceType,
isFirstChild: childView.id == childViews.first.id, isFirstChild: childView.id == widget.childViews.first.id,
view: childView, view: childView,
level: level + 1, level: widget.level + 1,
onSelected: onSelected, onSelected: widget.onSelected,
onTertiarySelected: onTertiarySelected, onTertiarySelected: widget.onTertiarySelected,
isDraggable: isDraggable, isDraggable: widget.isDraggable,
leftPadding: leftPadding, leftPadding: widget.leftPadding,
isFeedback: isFeedback, isFeedback: widget.isFeedback,
isPlaceholder: isPlaceholder, isPlaceholder: widget.isPlaceholder,
isHovered: isHovered, isHovered: widget.isHovered,
leftIconBuilder: leftIconBuilder, leftIconBuilder: widget.leftIconBuilder,
rightIconsBuilder: rightIconsBuilder, rightIconsBuilder: widget.rightIconsBuilder,
); );
}).toList(); }).toList();
@ -257,15 +283,15 @@ class InnerViewItem extends StatelessWidget {
} }
// wrap the child with DraggableItem if isDraggable is true // wrap the child with DraggableItem if isDraggable is true
if ((isDraggable || isPlaceholder) && if ((widget.isDraggable || widget.isPlaceholder) &&
!isReferencedDatabaseView(view, parentView)) { !isReferencedDatabaseView(widget.view, widget.parentView)) {
child = DraggableViewItem( child = DraggableViewItem(
isFirstChild: isFirstChild, isFirstChild: widget.isFirstChild,
view: view, view: widget.view,
onDragging: (isDragging) { onDragging: (isDragging) {
_isDragging = isDragging; _isDragging = isDragging;
}, },
onMove: isPlaceholder onMove: widget.isPlaceholder
? (from, to) => _moveViewCrossSection(context, from, to) ? (from, to) => _moveViewCrossSection(context, from, to)
: null, : null,
feedback: (context) { feedback: (context) {
@ -278,17 +304,17 @@ class InnerViewItem extends StatelessWidget {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: ViewItem( child: ViewItem(
view: view, view: widget.view,
parentView: parentView, parentView: widget.parentView,
spaceType: spaceType, spaceType: widget.spaceType,
level: level, level: widget.level,
onSelected: onSelected, onSelected: widget.onSelected,
onTertiarySelected: onTertiarySelected, onTertiarySelected: widget.onTertiarySelected,
isDraggable: false, isDraggable: false,
leftPadding: leftPadding, leftPadding: widget.leftPadding,
isFeedback: true, isFeedback: true,
leftIconBuilder: leftIconBuilder, leftIconBuilder: widget.leftIconBuilder,
rightIconsBuilder: rightIconsBuilder, rightIconsBuilder: widget.rightIconsBuilder,
), ),
); );
}, },
@ -305,18 +331,24 @@ class InnerViewItem extends StatelessWidget {
return child; return child;
} }
void _collapseAllPages() {
if (widget.isExpandedNotifier?.value == true) {
context.read<ViewBloc>().add(const ViewEvent.collapseAllPages());
}
}
void _moveViewCrossSection( void _moveViewCrossSection(
BuildContext context, BuildContext context,
ViewPB from, ViewPB from,
ViewPB to, ViewPB to,
) { ) {
if (isReferencedDatabaseView(view, parentView)) { if (isReferencedDatabaseView(widget.view, widget.parentView)) {
return; return;
} }
final fromSection = spaceType == FolderSpaceType.public final fromSection = widget.spaceType == FolderSpaceType.public
? ViewSectionPB.Private ? ViewSectionPB.Private
: ViewSectionPB.Public; : ViewSectionPB.Public;
final toSection = spaceType == FolderSpaceType.public final toSection = widget.spaceType == FolderSpaceType.public
? ViewSectionPB.Public ? ViewSectionPB.Public
: ViewSectionPB.Private; : ViewSectionPB.Private;
context.read<ViewBloc>().add( context.read<ViewBloc>().add(
@ -331,7 +363,7 @@ class InnerViewItem extends StatelessWidget {
context.read<ViewBloc>().add( context.read<ViewBloc>().add(
ViewEvent.updateViewVisibility( ViewEvent.updateViewVisibility(
from, from,
spaceType == FolderSpaceType.public, widget.spaceType == FolderSpaceType.public,
), ),
); );
} }

View File

@ -1,10 +1,9 @@
import 'package:flutter/material.dart';
import 'package:appflowy/workspace/application/settings/settings_dialog_bloc.dart'; import 'package:appflowy/workspace/application/settings/settings_dialog_bloc.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra/theme_extension.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/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart';
class SettingsMenuElement extends StatelessWidget { class SettingsMenuElement extends StatelessWidget {
const SettingsMenuElement({ const SettingsMenuElement({
@ -28,7 +27,7 @@ class SettingsMenuElement extends StatelessWidget {
isSelected: () => page == selectedPage, isSelected: () => page == selectedPage,
resetHoverOnRebuild: false, resetHoverOnRebuild: false,
style: HoverStyle( style: HoverStyle(
hoverColor: AFThemeExtension.of(context).greySelect, hoverColor: AFThemeExtension.of(context).greyHover,
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),
), ),
builder: (_, isHovering) => ListTile( builder: (_, isHovering) => ListTile(

View File

@ -103,7 +103,7 @@ class _MoreViewActionsState extends State<MoreViewActions> {
FlowySvgs.three_dots_s, FlowySvgs.three_dots_s,
size: const Size.square(18), size: const Size.square(18),
color: isHovering color: isHovering
? Theme.of(context).colorScheme.onSecondary ? Theme.of(context).colorScheme.onSurface
: Theme.of(context).iconTheme.color, : Theme.of(context).iconTheme.color,
), ),
), ),

View File

@ -117,10 +117,10 @@ class DefaultColorScheme extends FlowyColorScheme {
hint: const Color(0xFF59647a), hint: const Color(0xFF59647a),
primary: _darkMain2, primary: _darkMain2,
onPrimary: _darkShader1, onPrimary: _darkShader1,
hoverBG1: _darkMain1, hoverBG1: const Color(0x1AFFFFFF),
hoverBG2: _darkMain1, hoverBG2: _darkMain1,
hoverBG3: _darkShader3, hoverBG3: _darkShader3,
hoverFG: _darkShader1, hoverFG: const Color(0xE5FFFFFF),
questionBubbleBG: _darkShader3, questionBubbleBG: _darkShader3,
progressBarBGColor: _darkShader3, progressBarBGColor: _darkShader3,
toolbarColor: _darkInput, toolbarColor: _darkInput,