From 29fb4af40a6ca61cec6076b33c0eec9caa7e298e Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Fri, 26 Jul 2024 09:49:13 +0800 Subject: [PATCH] chore: improve UI design on Desktop (#5792) * fix: only show collapse page button when the children of the page is not emtpy * chore: set minimum sidebar width to 268 * chore: replace space lock icon and pin & unpin icon * chore: change divider color * chore: update divider color * chore: improve create space color * feat: highlight delete button when hovering * chore: update translations * fix: icon align issue * feat: highlight sidebar resizer when hovering * feat: add border to popover * feat: optimize scroll bar * feat: improve scrollbar hover color * feat: support creating a new page via cmd+n * chore: improve scrollbar color * feat: improve tooltip style * chore: fix unit test * chore: bump version 0.6.6 --- frontend/Makefile.toml | 2 +- .../lib/core/frameless_window.dart | 16 +- .../widgets/calculations/calculate_cell.dart | 8 +- .../align_toolbar_item.dart | 6 +- .../widgets/smart_edit_node_widget.dart | 5 - .../appearance/desktop_appearance.dart | 24 ++- .../appearance/mobile_appearance.dart | 6 +- .../home/desktop_home_screen.dart | 45 +---- .../presentation/home/home_layout.dart | 3 + .../presentation/home/home_sizes.dart | 1 + .../workspace/presentation/home/hotkeys.dart | 14 +- .../sidebar/favorites/favorite_folder.dart | 6 - .../menu/sidebar/favorites/favorite_menu.dart | 21 +-- .../favorites/favorite_pin_action.dart | 4 +- .../menu/sidebar/header/sidebar_top_menu.dart | 12 +- .../menu/sidebar/move_to/move_page_menu.dart | 19 ++- .../shared/sidebar_new_page_button.dart | 24 ++- .../home/menu/sidebar/sidebar.dart | 29 ++-- .../home/menu/sidebar/space/_extension.dart | 8 + .../sidebar/space/create_space_popup.dart | 14 +- .../menu/sidebar/space/shared_widget.dart | 68 ++++---- .../sidebar/space/sidebar_space_header.dart | 12 +- .../sidebar/space/sidebar_space_menu.dart | 4 +- .../menu/sidebar/space/space_action_type.dart | 18 +- .../menu/sidebar/space/space_icon_popup.dart | 6 - .../menu/sidebar/space/space_more_popup.dart | 28 +-- .../home/menu/view/view_action_type.dart | 25 ++- .../home/menu/view/view_item.dart | 1 + .../menu/view/view_more_action_button.dart | 27 +-- .../presentation/home/navigation.dart | 15 +- .../pages/settings_workspace_view.dart | 14 +- .../presentation/widgets/pop_up_action.dart | 4 +- .../presentation/widgets/sidebar_resizer.dart | 84 +++++++++ .../presentation/widgets/view_title_bar.dart | 1 + .../lib/colorscheme/colorscheme.dart | 11 +- .../lib/colorscheme/dandelion.dart | 7 + .../lib/colorscheme/default_colorscheme.dart | 160 ++++++++++-------- .../flowy_infra/lib/colorscheme/lavender.dart | 7 + .../flowy_infra/lib/colorscheme/lemonade.dart | 7 + .../flowy_infra/lib/theme_extension.dart | 21 +++ .../flowy_infra_ui/lib/flowy_infra_ui.dart | 2 + .../src/flowy_overlay/appflowy_popover.dart | 75 ++++++-- .../lib/style_widget/button.dart | 138 ++++++++++++++- .../lib/style_widget/decoration.dart | 2 + .../lib/style_widget/divider.dart | 17 ++ .../lib/style_widget/scrollbar.dart | 52 ++++++ .../scrolling/styled_scroll_bar.dart | 38 ++--- .../flowy_infra_ui/lib/style_widget/text.dart | 15 +- .../lib/widget/flowy_tooltip.dart | 36 +++- frontend/appflowy_flutter/pubspec.yaml | 2 +- .../flowy_icons/16x/favorite_section_pin.svg | 2 +- .../16x/favorite_section_unpin.svg | 4 +- .../resources/flowy_icons/16x/space_lock.svg | 6 +- frontend/resources/translations/en.json | 3 +- 54 files changed, 793 insertions(+), 386 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/_extension.dart create mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/sidebar_resizer.dart create mode 100644 frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/divider.dart create mode 100644 frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrollbar.dart diff --git a/frontend/Makefile.toml b/frontend/Makefile.toml index 3433449249..89c687bba7 100644 --- a/frontend/Makefile.toml +++ b/frontend/Makefile.toml @@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true CARGO_MAKE_CRATE_FS_NAME = "dart_ffi" CARGO_MAKE_CRATE_NAME = "dart-ffi" LIB_NAME = "dart_ffi" -APPFLOWY_VERSION = "0.6.5" +APPFLOWY_VERSION = "0.6.6" FLUTTER_DESKTOP_FEATURES = "dart" PRODUCT_NAME = "AppFlowy" MACOSX_DEPLOYMENT_TARGET = "11.0" diff --git a/frontend/appflowy_flutter/lib/core/frameless_window.dart b/frontend/appflowy_flutter/lib/core/frameless_window.dart index 799c90f5b7..ea6c730855 100644 --- a/frontend/appflowy_flutter/lib/core/frameless_window.dart +++ b/frontend/appflowy_flutter/lib/core/frameless_window.dart @@ -1,16 +1,14 @@ import 'dart:io'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/shared/window_title_bar.dart'; -import 'package:appflowy/util/theme_extension.dart'; import 'package:appflowy/workspace/application/home/home_setting_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class CocoaWindowChannel { @@ -104,19 +102,17 @@ class MoveWindowDetectorState extends State { return const SizedBox.shrink(); } - final color = Theme.of(context).isLightMode ? Colors.white : Colors.black; final textSpan = TextSpan( children: [ TextSpan( text: '${LocaleKeys.sideBar_openSidebar.tr()}\n', - style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: color), + style: context.tooltipTextStyle(), ), TextSpan( text: Platform.isMacOS ? '⌘+.' : 'Ctrl+\\', - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith(color: Theme.of(context).hintColor), + style: context + .tooltipTextStyle() + ?.copyWith(color: Theme.of(context).hintColor), ), ], ); diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/calculations/calculate_cell.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/calculations/calculate_cell.dart index c8199ce135..453247a8cb 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/calculations/calculate_cell.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/calculations/calculate_cell.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/plugins/database/application/calculations/calculation_type_ext.dart'; import 'package:appflowy/plugins/database/application/field/field_info.dart'; import 'package:appflowy/plugins/database/application/field/type_option/number_format_bloc.dart'; @@ -16,6 +14,7 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class CalculateCell extends StatefulWidget { @@ -141,11 +140,14 @@ class _CalculateCellState extends State { TextSpan( text: widget.calculation!.calculationType.shortLabel .toUpperCase(), + style: context.tooltipTextStyle(), ), const TextSpan(text: ' '), TextSpan( text: calculateValue, - style: const TextStyle(fontWeight: FontWeight.w500), + style: context + .tooltipTextStyle() + ?.copyWith(fontWeight: FontWeight.w500), ), ], ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/align_toolbar_item/align_toolbar_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/align_toolbar_item/align_toolbar_item.dart index a20618f961..266529b360 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/align_toolbar_item/align_toolbar_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/align_toolbar_item/align_toolbar_item.dart @@ -91,10 +91,8 @@ class _AlignmentButtonsState extends State<_AlignmentButtons> { margin: const EdgeInsets.all(4), direction: PopoverDirection.bottomWithCenterAligned, offset: const Offset(0, 10), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onTertiary, - borderRadius: const BorderRadius.all(Radius.circular(4)), - ), + decorationColor: Theme.of(context).colorScheme.onTertiary, + borderRadius: const BorderRadius.all(Radius.circular(4)), popupBuilder: (_) { keepEditorFocusNotifier.increase(); return _AlignButtons(onAlignChanged: widget.onAlignChanged); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_node_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_node_widget.dart index 299aa3a6d1..04e83fb758 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_node_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_node_widget.dart @@ -12,7 +12,6 @@ import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/decoration.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:provider/provider.dart'; @@ -118,10 +117,6 @@ class _SmartEditBlockComponentWidgetState triggerActions: PopoverTriggerFlags.none, margin: EdgeInsets.zero, constraints: BoxConstraints(maxWidth: width), - decoration: FlowyDecoration.decoration( - Colors.transparent, - Colors.transparent, - ), child: const SizedBox( width: double.infinity, ), diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/desktop_appearance.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/desktop_appearance.dart index f09e08a3d1..c6cf43bd16 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/desktop_appearance.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/desktop_appearance.dart @@ -1,9 +1,8 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme_extension.dart'; +import 'package:flutter/material.dart'; class DesktopAppearance extends BaseAppearance { @override @@ -75,18 +74,12 @@ class DesktopAppearance extends BaseAppearance { contentTextStyle: TextStyle(color: colorScheme.onSurface), ), scrollbarTheme: ScrollbarThemeData( - thumbColor: WidgetStateProperty.resolveWith((states) { - if (states.any(scrollbarInteractiveStates.contains)) { - return theme.shader3; - } - return theme.shader5; - }), - thickness: WidgetStateProperty.resolveWith((states) { - if (states.any(scrollbarInteractiveStates.contains)) { - return 4; - } - return 3.0; - }), + thumbColor: WidgetStateProperty.resolveWith( + (states) => states.any(scrollbarInteractiveStates.contains) + ? theme.scrollbarHoverColor + : theme.scrollbarColor, + ), + thickness: WidgetStateProperty.resolveWith((_) => 4.0), crossAxisMargin: 0.0, mainAxisMargin: 6.0, radius: Corners.s10Radius, @@ -147,6 +140,9 @@ class DesktopAppearance extends BaseAppearance { ), onBackground: theme.text, background: theme.surface, + borderColor: theme.borderColor, + scrollbarColor: theme.scrollbarColor, + scrollbarHoverColor: theme.scrollbarHoverColor, ), ], ); diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/mobile_appearance.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/mobile_appearance.dart index e2f1ee0006..b1ea4fa789 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/mobile_appearance.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/mobile_appearance.dart @@ -1,11 +1,10 @@ -import 'package:flutter/material.dart'; - // ThemeData in mobile import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_menu/_toolbar_theme.dart'; import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme_extension.dart'; +import 'package:flutter/material.dart'; class MobileAppearance extends BaseAppearance { static const _primaryColor = Color(0xFF00BCF0); //primary 100 @@ -276,6 +275,9 @@ class MobileAppearance extends BaseAppearance { ), onBackground: onBackground, background: background, + borderColor: theme.borderColor, + scrollbarColor: theme.scrollbarColor, + scrollbarHoverColor: theme.scrollbarHoverColor, ), ToolbarColorExtension.fromBrightness(brightness), ], diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart index 916ef0a774..f2e1515112 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart @@ -1,6 +1,3 @@ -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; - import 'package:appflowy/plugins/blank/blank.dart'; import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/startup/startup.dart'; @@ -27,12 +24,13 @@ import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show UserProfilePB; import 'package:flowy_infra_ui/style_widget/container.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:sized_context/sized_context.dart'; import 'package:styled_widget/styled_widget.dart'; import '../widgets/edit_panel/edit_panel.dart'; - +import '../widgets/sidebar_resizer.dart'; import 'home_layout.dart'; import 'home_stack.dart'; @@ -164,7 +162,9 @@ class DesktopHomeScreen extends StatelessWidget { userProfile: userProfile, workspaceSetting: workspaceSetting, ); - final homeMenuResizer = _buildHomeMenuResizer(context, layout: layout); + + final homeMenuResizer = + layout.showMenu ? const SidebarResizer() : const SizedBox.shrink(); final editPanel = _buildEditPanel(context, layout: layout); return _layoutWidgets( @@ -218,39 +218,6 @@ class DesktopHomeScreen extends StatelessWidget { ); } - Widget _buildHomeMenuResizer( - BuildContext context, { - required HomeLayout layout, - }) { - if (!layout.showMenu) { - return const SizedBox.shrink(); - } - - return MouseRegion( - cursor: SystemMouseCursors.resizeLeftRight, - child: GestureDetector( - dragStartBehavior: DragStartBehavior.down, - onHorizontalDragStart: (details) => context - .read() - .add(const HomeSettingEvent.editPanelResizeStart()), - onHorizontalDragUpdate: (details) => context - .read() - .add(HomeSettingEvent.editPanelResized(details.localPosition.dx)), - onHorizontalDragEnd: (details) => context - .read() - .add(const HomeSettingEvent.editPanelResizeEnd()), - onHorizontalDragCancel: () => context - .read() - .add(const HomeSettingEvent.editPanelResizeEnd()), - behavior: HitTestBehavior.translucent, - child: SizedBox( - width: 10, - height: MediaQuery.of(context).size.height, - ), - ), - ); - } - Widget _layoutWidgets({ required HomeLayout layout, required Widget sidebar, @@ -296,7 +263,7 @@ class DesktopHomeScreen extends StatelessWidget { ) .positioned(left: 0, top: 0, width: layout.menuWidth, bottom: 0), homeMenuResizer - .positioned(left: layout.menuWidth - 5) + .positioned(left: layout.menuWidth) .animate(layout.animDuration, Curves.easeOutQuad), ], ); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_layout.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_layout.dart index 1da2ca32fa..fb108b702e 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_layout.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_layout.dart @@ -1,4 +1,5 @@ import 'dart:io' show Platform; +import 'dart:math'; import 'package:appflowy/workspace/application/home/home_setting_bloc.dart'; import 'package:flowy_infra/size.dart'; @@ -16,6 +17,8 @@ class HomeLayout { menuWidth = Sizes.sideBarWidth; menuWidth += homeSetting.resizeOffset; + menuWidth = max(menuWidth, HomeSizes.minimumSidebarWidth); + final screenWidthPx = context.widthPx; context .read() diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_sizes.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_sizes.dart index b35ae64ac5..18d76057a2 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_sizes.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_sizes.dart @@ -8,6 +8,7 @@ class HomeSizes { static const double workspaceSectionHeight = 32; static const double searchSectionHeight = 30; static const double newPageSectionHeight = 30; + static const double minimumSidebarWidth = 268; } class HomeInsets { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/hotkeys.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/hotkeys.dart index 1fb9a00658..b5e2e3ec91 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/hotkeys.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/hotkeys.dart @@ -1,7 +1,5 @@ import 'dart:io'; -import 'package:flutter/material.dart'; - import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/tasks/app_window_size_manager.dart'; import 'package:appflowy/workspace/application/home/home_setting_bloc.dart'; @@ -11,6 +9,7 @@ import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_setting.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; +import 'package:flutter/material.dart'; import 'package:hotkey_manager/hotkey_manager.dart'; import 'package:provider/provider.dart'; import 'package:scaled_app/scaled_app.dart'; @@ -18,6 +17,7 @@ import 'package:scaled_app/scaled_app.dart'; typedef KeyDownHandler = void Function(HotKey hotKey); ValueNotifier switchToTheNextSpace = ValueNotifier(0); +ValueNotifier createNewPageNotifier = ValueNotifier(0); /// Helper class that utilizes the global [HotKeyManager] to easily /// add a [HotKey] with different handlers. @@ -180,6 +180,16 @@ class _HomeHotKeysState extends State { keyDownHandler: (_) => switchToTheNextSpace.value++, ), + // Create a new page + HotKeyItem( + hotKey: HotKey( + KeyCode.keyN, + modifiers: [Platform.isMacOS ? KeyModifier.meta : KeyModifier.control], + scope: HotKeyScope.inapp, + ), + keyDownHandler: (_) => createNewPageNotifier.value++, + ), + // Open settings dialog openSettingsHotKey(context, widget.userProfile), ]; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_folder.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_folder.dart index f73fa04cd0..1bfc324088 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_folder.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_folder.dart @@ -11,7 +11,6 @@ import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/decoration.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -172,11 +171,6 @@ class FavoriteMoreButton extends StatelessWidget { constraints: const BoxConstraints( minWidth: minWidth, ), - decoration: FlowyDecoration.decoration( - Theme.of(context).cardColor, - Theme.of(context).colorScheme.shadow, - borderRadius: 10.0, - ), popupBuilder: (_) { return MultiBlocProvider( providers: [ diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_menu.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_menu.dart index 4449558bb6..3141c23b31 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_menu.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_menu.dart @@ -137,6 +137,7 @@ class _FavoriteGroups extends StatelessWidget { state.otherViews, LocaleKeys.sideBar_others.tr(), ); + return Container( width: minWidth - 2 * _kHorizontalPadding, constraints: const BoxConstraints( @@ -149,15 +150,14 @@ class _FavoriteGroups extends StatelessWidget { children: [ if (today.isNotEmpty) ...[ ...today, - const VSpace(8), - const Divider(height: 1), - const VSpace(8), + const FlowyDivider(), + const VSpace(16), ], if (thisWeek.isNotEmpty) ...[ ...thisWeek, const VSpace(8), - const Divider(height: 1), - const VSpace(8), + const FlowyDivider(), + const VSpace(16), ], ...others.isNotEmpty && (today.isNotEmpty || thisWeek.isNotEmpty) ? others @@ -182,13 +182,10 @@ class _FavoriteGroups extends StatelessWidget { return [ if (views.isNotEmpty) ...[ if (showHeader) - SizedBox( - height: 24, - child: FlowyText( - title, - fontSize: 12.0, - color: Theme.of(context).hintColor, - ), + FlowyText( + title, + fontSize: 12.0, + color: Theme.of(context).hintColor, ), const VSpace(2), _FavoriteGroupedViews(views: views), diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_pin_action.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_pin_action.dart index 2a849b7e8d..de293d894d 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_pin_action.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_pin_action.dart @@ -21,8 +21,8 @@ class FavoritePinAction extends StatelessWidget { : LocaleKeys.favorite_addToSidebar.tr(); final icon = FlowySvg( view.isPinned - ? FlowySvgs.favorite_section_pin_s - : FlowySvgs.favorite_section_unpin_s, + ? FlowySvgs.favorite_section_unpin_s + : FlowySvgs.favorite_section_pin_s, ); return FlowyTooltip( message: tooltip, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/header/sidebar_top_menu.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/header/sidebar_top_menu.dart index 674febd610..7c8db674b0 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/header/sidebar_top_menu.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/header/sidebar_top_menu.dart @@ -3,7 +3,6 @@ import 'dart:io' show Platform; import 'package:appflowy/core/frameless_window.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/util/theme_extension.dart'; import 'package:appflowy/workspace/application/home/home_setting_bloc.dart'; import 'package:appflowy/workspace/application/menu/sidebar_sections_bloc.dart'; import 'package:appflowy/workspace/presentation/home/home_sizes.dart'; @@ -65,20 +64,17 @@ class SidebarTopMenu extends StatelessWidget { } Widget _buildCollapseMenuButton(BuildContext context) { - final color = Theme.of(context).isLightMode ? Colors.white : Colors.black; final textSpan = TextSpan( children: [ TextSpan( text: '${LocaleKeys.sideBar_closeSidebar.tr()}\n', - style: - Theme.of(context).tooltipTheme.textStyle!.copyWith(color: color), + style: context.tooltipTextStyle(), ), TextSpan( text: Platform.isMacOS ? '⌘+.' : 'Ctrl+\\', - style: Theme.of(context) - .tooltipTheme - .textStyle! - .copyWith(color: Theme.of(context).hintColor), + style: context + .tooltipTextStyle() + ?.copyWith(color: Theme.of(context).hintColor), ), ], ); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/move_to/move_page_menu.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/move_to/move_page_menu.dart index 7fb3c6902f..03a69e0865 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/move_to/move_page_menu.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/move_to/move_page_menu.dart @@ -1,3 +1,4 @@ +import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart'; import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart'; import 'package:appflowy/workspace/application/sidebar/space/space_search_bloc.dart'; @@ -5,9 +6,12 @@ import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/shared_widget.dart'; import 'package:appflowy/workspace/presentation/home/menu/view/view_item.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-user/protobuf.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -123,12 +127,15 @@ class _MovePageMenuState extends State { expand: true, height: 30, showCreateButton: false, - child: CurrentSpace( - onTapBlankArea: () { - // move the page to current space - widget.onSelected(space, space); - }, - space: space, + child: FlowyTooltip( + message: LocaleKeys.space_switchSpace.tr(), + child: CurrentSpace( + onTapBlankArea: () { + // move the page to current space + widget.onSelected(space, space); + }, + space: space, + ), ), ), Expanded( diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/shared/sidebar_new_page_button.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/shared/sidebar_new_page_button.dart index 8f072356d1..6fdd0d65b7 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/shared/sidebar_new_page_button.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/shared/sidebar_new_page_button.dart @@ -4,6 +4,7 @@ import 'package:appflowy/workspace/application/menu/sidebar_sections_bloc.dart'; import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart'; import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart'; import 'package:appflowy/workspace/presentation/home/home_sizes.dart'; +import 'package:appflowy/workspace/presentation/home/hotkeys.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/rename_view_dialog.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -11,18 +12,35 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -class SidebarNewPageButton extends StatelessWidget { +class SidebarNewPageButton extends StatefulWidget { const SidebarNewPageButton({ super.key, }); + @override + State createState() => _SidebarNewPageButtonState(); +} + +class _SidebarNewPageButtonState extends State { + @override + void initState() { + super.initState(); + createNewPageNotifier.addListener(_createNewPage); + } + + @override + void dispose() { + createNewPageNotifier.removeListener(_createNewPage); + super.dispose(); + } + @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 8), height: HomeSizes.newPageSectionHeight, child: FlowyButton( - onTap: () async => _createNewPage(context), + onTap: () async => _createNewPage(), leftIcon: const FlowySvg( FlowySvgs.new_app_m, blendMode: null, @@ -38,7 +56,7 @@ class SidebarNewPageButton extends StatelessWidget { ); } - Future _createNewPage(BuildContext context) async { + Future _createNewPage() async { return createViewAndShowRenameDialogIfNeeded( context, LocaleKeys.newPageText.tr(), diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar.dart index b87e62ccbe..3481981130 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar.dart @@ -1,7 +1,5 @@ import 'dart:async'; -import 'package:flutter/material.dart'; - import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/blank/blank.dart'; @@ -35,9 +33,8 @@ import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show UserProfilePB; import 'package:appflowy_editor/appflowy_editor.dart' hide Log; import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; Loading? _duplicateSpaceLoading; @@ -333,10 +330,7 @@ class _SidebarState extends State<_Sidebar> { child: child, ); }, - child: const Divider( - color: Color(0x141F2329), - height: 0.5, - ), + child: const FlowyDivider(), ), ), @@ -346,7 +340,7 @@ class _SidebarState extends State<_Sidebar> { Padding( padding: menuHorizontalInset + const EdgeInsets.symmetric(horizontal: 4.0), - child: const Divider(height: 0.5, color: Color(0x141F2329)), + child: const FlowyDivider(), ), const VSpace(8), @@ -403,13 +397,16 @@ class _SidebarState extends State<_Sidebar> { : Expanded( child: Padding( padding: menuHorizontalInset - const EdgeInsets.only(right: 6), - child: SingleChildScrollView( - padding: const EdgeInsets.only(right: 6), + child: FlowyScrollbar( controller: _scrollController, - physics: const ClampingScrollPhysics(), - child: SidebarSpace( - userProfile: widget.userProfile, - isHoverEnabled: !_isScrolling, + child: SingleChildScrollView( + padding: const EdgeInsets.only(right: 6), + controller: _scrollController, + physics: const ClampingScrollPhysics(), + child: SidebarSpace( + userProfile: widget.userProfile, + isHoverEnabled: !_isScrolling, + ), ), ), ), diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/_extension.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/_extension.dart new file mode 100644 index 0000000000..40f20f098a --- /dev/null +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/_extension.dart @@ -0,0 +1,8 @@ +import 'package:appflowy/util/theme_extension.dart'; +import 'package:flutter/material.dart'; + +extension SpacePermissionColorExtension on BuildContext { + Color get enableBorderColor => Theme.of(this).isLightMode + ? const Color(0x1E171717) + : const Color(0xFF3A3F49); +} diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/create_space_popup.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/create_space_popup.dart index 328c969729..d46982f377 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/create_space_popup.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/create_space_popup.dart @@ -1,5 +1,6 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart'; +import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/_extension.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/shared_widget.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/space_icon_popup.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -24,19 +25,22 @@ class _CreateSpacePopupState extends State { Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0), - width: 500, + width: 524, child: Column( mainAxisSize: MainAxisSize.min, children: [ FlowyText( LocaleKeys.space_createNewSpace.tr(), fontSize: 18.0, + figmaLineHeight: 24.0, ), - const VSpace(6.0), - FlowyText.regular( + const VSpace(2.0), + FlowyText( LocaleKeys.space_createSpaceDescription.tr(), fontSize: 14.0, + fontWeight: FontWeight.w300, color: Theme.of(context).hintColor, + figmaLineHeight: 18.0, maxLines: 2, ), const VSpace(16.0), @@ -106,14 +110,16 @@ class _SpaceNameTextField extends StatelessWidget { LocaleKeys.space_spaceName.tr(), fontSize: 14.0, color: Theme.of(context).hintColor, + figmaLineHeight: 18.0, ), const VSpace(6.0), SizedBox( height: 40, child: FlowyTextField( - hintText: LocaleKeys.space_spaceName.tr(), + hintText: LocaleKeys.space_spaceNamePlaceholder.tr(), onChanged: onChanged, onSubmitted: onSubmitted, + enableBorderColor: context.enableBorderColor, ), ), ], diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/shared_widget.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/shared_widget.dart index 97b4f18bcf..61e2f0ac46 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/shared_widget.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/shared_widget.dart @@ -1,7 +1,3 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/util/theme_extension.dart'; @@ -10,6 +6,7 @@ import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart'; import 'package:appflowy/workspace/application/view/view_bloc.dart'; import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy/workspace/presentation/home/home_sizes.dart'; +import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/_extension.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/sidebar_space_menu.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/space_icon.dart'; import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart'; @@ -19,9 +16,11 @@ import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/decoration.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class SpacePermissionSwitch extends StatefulWidget { @@ -55,6 +54,7 @@ class _SpacePermissionSwitchState extends State { LocaleKeys.space_permission.tr(), fontSize: 14.0, color: Theme.of(context).hintColor, + figmaLineHeight: 18.0, ), const VSpace(6.0), AppFlowyPopover( @@ -63,16 +63,11 @@ class _SpacePermissionSwitchState extends State { constraints: const BoxConstraints(maxWidth: 500), offset: const Offset(0, 4), margin: EdgeInsets.zero, - decoration: FlowyDecoration.decoration( - Theme.of(context).cardColor, - Theme.of(context).colorScheme.shadow, - borderRadius: 10, - ), popupBuilder: (_) => _buildPermissionButtons(), child: DecoratedBox( decoration: ShapeDecoration( shape: RoundedRectangleBorder( - side: BorderSide(color: Theme.of(context).colorScheme.outline), + side: BorderSide(color: context.enableBorderColor), borderRadius: BorderRadius.circular(10), ), ), @@ -148,9 +143,13 @@ class SpacePermissionButton extends StatelessWidget { radius: BorderRadius.circular(10), iconPadding: 16.0, leftIcon: FlowySvg(icon), + leftIconSize: const Size.square(20), rightIcon: showArrow ? const FlowySvg(FlowySvgs.space_permission_dropdown_s) : null, + borderColor: Theme.of(context).isLightMode + ? const Color(0x1E171717) + : const Color(0xFF3A3F49), text: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -462,32 +461,29 @@ class CurrentSpace extends StatelessWidget { @override Widget build(BuildContext context) { - final child = FlowyTooltip( - message: LocaleKeys.space_switchSpace.tr(), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - SpaceIcon( - dimension: 20, - space: space, - cornerRadius: 6.0, + final child = Row( + mainAxisSize: MainAxisSize.min, + children: [ + SpaceIcon( + dimension: 20, + space: space, + cornerRadius: 6.0, + ), + const HSpace(10), + Flexible( + child: FlowyText.medium( + space.name, + fontSize: 14.0, + overflow: TextOverflow.ellipsis, ), - const HSpace(10), - Flexible( - child: FlowyText.medium( - space.name, - fontSize: 14.0, - overflow: TextOverflow.ellipsis, - ), - ), - const HSpace(4.0), - FlowySvg( - context.read().state.isExpanded - ? FlowySvgs.workspace_drop_down_menu_show_s - : FlowySvgs.workspace_drop_down_menu_hide_s, - ), - ], - ), + ), + const HSpace(4.0), + FlowySvg( + context.read().state.isExpanded + ? FlowySvgs.workspace_drop_down_menu_show_s + : FlowySvgs.workspace_drop_down_menu_hide_s, + ), + ], ); if (onTapBlankArea != null) { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/sidebar_space_header.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/sidebar_space_header.dart index 2eaafe90f9..0654c11e7b 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/sidebar_space_header.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/sidebar_space_header.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/util/theme_extension.dart'; import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart'; import 'package:appflowy/workspace/presentation/home/home_sizes.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/manage_space_popup.dart'; @@ -105,20 +104,17 @@ class _SidebarSpaceHeaderState extends State { } Widget _buildChild() { - final color = Theme.of(context).isLightMode ? Colors.white : Colors.black; final textSpan = TextSpan( children: [ TextSpan( text: '${LocaleKeys.space_quicklySwitch.tr()}\n', - style: - Theme.of(context).tooltipTheme.textStyle!.copyWith(color: color), + style: context.tooltipTextStyle(), ), TextSpan( text: Platform.isMacOS ? '⌘+O' : 'Ctrl+O', - style: Theme.of(context) - .tooltipTheme - .textStyle! - .copyWith(color: Theme.of(context).hintColor), + style: context + .tooltipTextStyle() + ?.copyWith(color: Theme.of(context).hintColor), ), ], ); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/sidebar_space_menu.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/sidebar_space_menu.dart index 9ff798ee5d..5a21780186 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/sidebar_space_menu.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/sidebar_space_menu.dart @@ -40,9 +40,7 @@ class SidebarSpaceMenu extends StatelessWidget { if (showCreateButton) ...[ const Padding( padding: EdgeInsets.symmetric(vertical: 8.0), - child: Divider( - height: 0.5, - ), + child: FlowyDivider(), ), const SizedBox( height: HomeSpaceViewSizes.viewHeight, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_action_type.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_action_type.dart index 5edf2d82b6..be0eadd8ed 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_action_type.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_action_type.dart @@ -36,24 +36,24 @@ extension ViewMoreActionTypeExtension on SpaceMoreActionType { } } - Widget get leftIcon { + FlowySvgData get leftIconSvg { switch (this) { case SpaceMoreActionType.delete: - return const FlowySvg(FlowySvgs.trash_s, blendMode: null); + return FlowySvgs.trash_s; case SpaceMoreActionType.rename: - return const FlowySvg(FlowySvgs.view_item_rename_s); + return FlowySvgs.view_item_rename_s; case SpaceMoreActionType.changeIcon: - return const FlowySvg(FlowySvgs.change_icon_s); + return FlowySvgs.change_icon_s; case SpaceMoreActionType.collapseAllPages: - return const FlowySvg(FlowySvgs.collapse_all_page_s); + return FlowySvgs.collapse_all_page_s; case SpaceMoreActionType.addNewSpace: - return const FlowySvg(FlowySvgs.space_add_s); + return FlowySvgs.space_add_s; case SpaceMoreActionType.manage: - return const FlowySvg(FlowySvgs.space_manage_s); + return FlowySvgs.space_manage_s; case SpaceMoreActionType.duplicate: - return const FlowySvg(FlowySvgs.duplicate_s); + return FlowySvgs.duplicate_s; case SpaceMoreActionType.divider: - return const SizedBox.shrink(); + throw UnsupportedError('Divider does not have an icon'); } } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_icon_popup.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_icon_popup.dart index feeea05e8c..091f288552 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_icon_popup.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_icon_popup.dart @@ -3,7 +3,6 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/style_widget/decoration.dart'; import 'package:flutter/material.dart'; final builtInSpaceColors = [ @@ -59,11 +58,6 @@ class _SpaceIconPopupState extends State { Widget build(BuildContext context) { return AppFlowyPopover( offset: const Offset(0, 4), - decoration: FlowyDecoration.decoration( - Theme.of(context).cardColor, - Theme.of(context).colorScheme.shadow, - borderRadius: 10, - ), constraints: const BoxConstraints(maxWidth: 220), margin: const EdgeInsets.symmetric(horizontal: 14.0, vertical: 12.0), direction: PopoverDirection.bottomWithCenterAligned, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_more_popup.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_more_popup.dart index 3ee4f215db..266ea62e72 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_more_popup.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/space/space_more_popup.dart @@ -129,7 +129,7 @@ class SpaceMoreActionTypeWrapper extends CustomActionCell { Widget _buildDivider() { return const Padding( padding: EdgeInsets.all(8.0), - child: Divider(height: 1.0), + child: FlowyDivider(), ); } @@ -158,22 +158,24 @@ class SpaceMoreActionTypeWrapper extends CustomActionCell { padding: const EdgeInsets.symmetric(vertical: 2.0), child: Opacity( opacity: disable ? 0.3 : 1.0, - child: FlowyButton( + child: FlowyIconTextButton( disable: disable, margin: const EdgeInsets.symmetric(horizontal: 6), - leftIcon: inner.leftIcon, - rightIcon: inner.rightIcon, iconPadding: 10.0, - text: SizedBox( - // height: 16.0, - child: FlowyText.regular( - inner.name, - color: inner == SpaceMoreActionType.delete - ? Theme.of(context).colorScheme.error - : null, - ), - ), onTap: onTap, + leftIconBuilder: (onHover) => FlowySvg( + inner.leftIconSvg, + color: inner == SpaceMoreActionType.delete && onHover + ? Theme.of(context).colorScheme.error + : null, + ), + rightIconBuilder: (_) => inner.rightIcon, + textBuilder: (onHover) => FlowyText.regular( + inner.name, + color: inner == SpaceMoreActionType.delete && onHover + ? Theme.of(context).colorScheme.error + : null, + ), ), ), ); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_action_type.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_action_type.dart index 3065eb7495..fe2e5def48 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_action_type.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_action_type.dart @@ -49,32 +49,31 @@ extension ViewMoreActionTypeExtension on ViewMoreActionType { } } - Widget get leftIcon { + FlowySvgData get leftIconSvg { switch (this) { case ViewMoreActionType.delete: - return const FlowySvg(FlowySvgs.trash_s, blendMode: null); + return FlowySvgs.trash_s; case ViewMoreActionType.favorite: - return const FlowySvg(FlowySvgs.favorite_s); + return FlowySvgs.favorite_s; case ViewMoreActionType.unFavorite: - return const FlowySvg(FlowySvgs.unfavorite_s); + return FlowySvgs.unfavorite_s; case ViewMoreActionType.duplicate: - return const FlowySvg(FlowySvgs.duplicate_s); - case ViewMoreActionType.copyLink: - return const Icon(Icons.copy); + return FlowySvgs.duplicate_s; case ViewMoreActionType.rename: - return const FlowySvg(FlowySvgs.view_item_rename_s); + return FlowySvgs.view_item_rename_s; case ViewMoreActionType.moveTo: - return const FlowySvg(FlowySvgs.move_to_s); + return FlowySvgs.move_to_s; case ViewMoreActionType.openInNewTab: - return const FlowySvg(FlowySvgs.view_item_open_in_new_tab_s); + return FlowySvgs.view_item_open_in_new_tab_s; case ViewMoreActionType.changeIcon: - return const FlowySvg(FlowySvgs.change_icon_s); + return FlowySvgs.change_icon_s; case ViewMoreActionType.collapseAllPages: - return const FlowySvg(FlowySvgs.collapse_all_page_s); + return FlowySvgs.collapse_all_page_s; case ViewMoreActionType.divider: case ViewMoreActionType.lastModified: + case ViewMoreActionType.copyLink: case ViewMoreActionType.created: - return const SizedBox.shrink(); + throw UnsupportedError('No left icon for $this'); } } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart index 5ad37d0e49..8a2b207450 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart @@ -491,6 +491,7 @@ class _SingleInnerViewItemState extends State { final name = FlowyText.regular( widget.view.name, overflow: TextOverflow.ellipsis, + // figmaLineHeight: 18.0, ); final children = [ const HSpace(2), diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart index 9b472fc57d..6a10db604e 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart @@ -101,7 +101,8 @@ class ViewMoreActionButton extends StatelessWidget { ]); // Chat doesn't change collapse - if (view.layout != ViewLayoutPB.Chat) { + // Only show collapse all pages if the view has child views + if (view.layout != ViewLayoutPB.Chat && view.childViews.isNotEmpty) { actionTypes.add(ViewMoreActionType.collapseAllPages); actionTypes.add(ViewMoreActionType.divider); } @@ -204,7 +205,7 @@ class ViewMoreActionTypeWrapper extends CustomActionCell { Widget _buildDivider() { return const Padding( padding: EdgeInsets.all(8.0), - child: Divider(height: 1.0), + child: FlowyDivider(), ); } @@ -237,18 +238,24 @@ class ViewMoreActionTypeWrapper extends CustomActionCell { return Container( height: 34, padding: const EdgeInsets.symmetric(vertical: 2.0), - child: FlowyButton( + child: FlowyIconTextButton( margin: const EdgeInsets.symmetric(horizontal: 6), - leftIcon: inner.leftIcon, - rightIcon: inner.rightIcon, - iconPadding: 10.0, - text: FlowyText.regular( - inner.name, - color: inner == ViewMoreActionType.delete + onTap: onTap, + // show the error color when delete is hovered + leftIconBuilder: (onHover) => FlowySvg( + inner.leftIconSvg, + color: inner == ViewMoreActionType.delete && onHover + ? Theme.of(context).colorScheme.error + : null, + ), + rightIconBuilder: (_) => inner.rightIcon, + iconPadding: 10.0, + textBuilder: (onHover) => FlowyText.regular( + inner.name, + color: inner == ViewMoreActionType.delete && onHover ? Theme.of(context).colorScheme.error : null, ), - onTap: onTap, ), ); } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/navigation.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/navigation.dart index a90c12565a..820fae7294 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/navigation.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/navigation.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/util/theme_extension.dart'; import 'package:appflowy/workspace/application/home/home_setting_bloc.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; @@ -65,23 +64,17 @@ class FlowyNavigation extends StatelessWidget { buildWhen: (p, c) => p.isMenuCollapsed != c.isMenuCollapsed, builder: (context, state) { if (!PlatformExtension.isWindows && state.isMenuCollapsed) { - final color = - Theme.of(context).isLightMode ? Colors.white : Colors.black; final textSpan = TextSpan( children: [ TextSpan( text: '${LocaleKeys.sideBar_openSidebar.tr()}\n', - style: Theme.of(context) - .tooltipTheme - .textStyle! - .copyWith(color: color), + style: context.tooltipTextStyle(), ), TextSpan( text: Platform.isMacOS ? '⌘+.' : 'Ctrl+\\', - style: Theme.of(context) - .tooltipTheme - .textStyle! - .copyWith(color: Theme.of(context).hintColor), + style: context + .tooltipTextStyle() + ?.copyWith(color: Theme.of(context).hintColor), ), ], ); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart index 7119761694..3bb810e6d5 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_workspace_view.dart @@ -1,7 +1,5 @@ import 'dart:async'; -import 'package:flutter/material.dart'; - import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart'; @@ -45,6 +43,7 @@ import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -879,16 +878,7 @@ class _FontSelectorDropdownState extends State<_FontSelectorDropdown> { maxHeight: 150, maxWidth: constraints.maxWidth - 90, ), - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: const BorderRadius.all(Radius.circular(4.0)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.10), - blurRadius: 6, - ), - ], - ), + borderRadius: const BorderRadius.all(Radius.circular(4.0)), popupBuilder: (_) => _FontListPopup( currentFont: appearance.font, scrollController: _scrollController, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/pop_up_action.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/pop_up_action.dart index 379104b94a..17f78cb8cf 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/pop_up_action.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/pop_up_action.dart @@ -1,8 +1,7 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; +import 'package:flutter/material.dart'; import 'package:styled_widget/styled_widget.dart'; class PopoverActionList extends StatefulWidget { @@ -54,7 +53,6 @@ class _PopoverActionListState @override Widget build(BuildContext context) { final child = widget.buildChild(popoverController); - return AppFlowyPopover( asBarrier: widget.asBarrier, controller: popoverController, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/sidebar_resizer.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/sidebar_resizer.dart new file mode 100644 index 0000000000..f229951e04 --- /dev/null +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/sidebar_resizer.dart @@ -0,0 +1,84 @@ +import 'package:appflowy/workspace/application/home/home_setting_bloc.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class SidebarResizer extends StatefulWidget { + const SidebarResizer({super.key}); + + @override + State createState() => _SidebarResizerState(); +} + +class _SidebarResizerState extends State { + final ValueNotifier isHovered = ValueNotifier(false); + final ValueNotifier isDragging = ValueNotifier(false); + + @override + void dispose() { + isHovered.dispose(); + isDragging.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return MouseRegion( + cursor: SystemMouseCursors.resizeLeftRight, + onEnter: (_) => isHovered.value = true, + onExit: (_) => isHovered.value = false, + child: GestureDetector( + dragStartBehavior: DragStartBehavior.down, + behavior: HitTestBehavior.translucent, + onHorizontalDragStart: (details) { + isDragging.value = true; + + context + .read() + .add(const HomeSettingEvent.editPanelResizeStart()); + }, + onHorizontalDragUpdate: (details) { + isDragging.value = true; + + context + .read() + .add(HomeSettingEvent.editPanelResized(details.localPosition.dx)); + }, + onHorizontalDragEnd: (details) { + isDragging.value = false; + + context + .read() + .add(const HomeSettingEvent.editPanelResizeEnd()); + }, + onHorizontalDragCancel: () { + isDragging.value = false; + + context + .read() + .add(const HomeSettingEvent.editPanelResizeEnd()); + }, + child: ValueListenableBuilder( + valueListenable: isHovered, + builder: (context, isHovered, _) { + return ValueListenableBuilder( + valueListenable: isDragging, + builder: (context, isDragging, _) { + return Container( + width: 2, + // increase the width of the resizer to make it easier to drag + margin: const EdgeInsets.only(right: 2.0), + height: MediaQuery.of(context).size.height, + color: isHovered || isDragging + ? const Color(0xFF00B5FF) + : Colors.transparent, + ); + }, + ); + }, + ), + ), + ); + } +} diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/view_title_bar.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/view_title_bar.dart index 7f06849908..70fee32a10 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/view_title_bar.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/view_title_bar.dart @@ -246,6 +246,7 @@ class _ViewTitleState extends State<_ViewTitle> { opacity: isEditable ? 1.0 : 0.5, child: FlowyText.regular( state.name, + fontSize: 14.0, overflow: TextOverflow.ellipsis, ), ), diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart index 14941e5477..0155e73240 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart @@ -1,7 +1,6 @@ -import 'package:flutter/material.dart'; - import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/utils/color_converter.dart'; +import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dandelion.dart'; @@ -87,6 +86,9 @@ class FlowyColorScheme { required this.toggleButtonBGColor, required this.calendarWeekendBGColor, required this.gridRowCountColor, + required this.borderColor, + required this.scrollbarColor, + required this.scrollbarHoverColor, }); final Color surface; @@ -145,6 +147,11 @@ class FlowyColorScheme { //grid bottom count color final Color gridRowCountColor; + final Color borderColor; + + final Color scrollbarColor; + final Color scrollbarHoverColor; + factory FlowyColorScheme.fromJson(Map json) => _$FlowyColorSchemeFromJson(json); diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart index 9ca6bf1045..ddb64c70ec 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart @@ -1,3 +1,4 @@ +import 'package:flowy_infra/colorscheme/default_colorscheme.dart'; import 'package:flutter/material.dart'; import 'colorscheme.dart'; @@ -81,6 +82,9 @@ class DandelionColorScheme extends FlowyColorScheme { toggleButtonBGColor: _lightDandelionYellow, calendarWeekendBGColor: const Color(0xFFFBFBFC), gridRowCountColor: _black, + borderColor: ColorSchemeConstants.lightBorderColor, + scrollbarColor: const Color(0x3F171717), + scrollbarHoverColor: const Color(0x7F171717), ); const DandelionColorScheme.dark() @@ -135,5 +139,8 @@ class DandelionColorScheme extends FlowyColorScheme { toggleButtonBGColor: _darkShader1, calendarWeekendBGColor: const Color(0xff121212), gridRowCountColor: _darkMain1, + borderColor: ColorSchemeConstants.darkBorderColor, + scrollbarColor: const Color(0x40FFFFFF), + scrollbarHoverColor: const Color(0x80FFFFFF), ); } diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart index 94c59302f1..a58e257c22 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart @@ -2,44 +2,48 @@ import 'package:flutter/material.dart'; import 'colorscheme.dart'; -const _white = Color(0xFFFFFFFF); -const _lightHover = Color(0xFFe0f8FF); -const _lightSelector = Color(0xFFf2fcFF); -const _lightBg1 = Color(0xFFf7f8fc); -const _lightBg2 = Color(0x0F1F2329); -const _lightShader1 = Color(0xFF333333); -const _lightShader3 = Color(0xFF828282); -const _lightShader5 = Color(0xFFe0e0e0); -const _lightShader6 = Color(0xFFf2f2f2); -const _lightMain1 = Color(0xFF00bcf0); -const _lightTint9 = Color(0xFFe1fbFF); -const _darkShader1 = Color(0xFF131720); -const _darkShader2 = Color(0xFF1A202C); -const _darkShader3 = Color(0xFF363D49); -const _darkShader5 = Color(0xFFBBC3CD); -const _darkShader6 = Color(0xFFF2F2F2); -const _darkMain1 = Color(0xFF00BCF0); -const _darkMain2 = Color(0xFF00BCF0); -const _darkInput = Color(0xFF282E3A); +class ColorSchemeConstants { + static const white = Color(0xFFFFFFFF); + static const lightHover = Color(0xFFe0f8FF); + static const lightSelector = Color(0xFFf2fcFF); + static const lightBg1 = Color(0xFFf7f8fc); + static const lightBg2 = Color(0x0F1F2329); + static const lightShader1 = Color(0xFF333333); + static const lightShader3 = Color(0xFF828282); + static const lightShader5 = Color(0xFFe0e0e0); + static const lightShader6 = Color(0xFFf2f2f2); + static const lightMain1 = Color(0xFF00bcf0); + static const lightTint9 = Color(0xFFe1fbFF); + static const darkShader1 = Color(0xFF131720); + static const darkShader2 = Color(0xFF1A202C); + static const darkShader3 = Color(0xFF363D49); + static const darkShader5 = Color(0xFFBBC3CD); + static const darkShader6 = Color(0xFFF2F2F2); + static const darkMain1 = Color(0xFF00BCF0); + static const darkMain2 = Color(0xFF00BCF0); + static const darkInput = Color(0xFF282E3A); + static const lightBorderColor = Color(0xFFEDEDEE); + static const darkBorderColor = Color(0xFF3A3F49); +} class DefaultColorScheme extends FlowyColorScheme { const DefaultColorScheme.light() : super( - surface: _white, - hover: _lightHover, - selector: _lightSelector, + surface: ColorSchemeConstants.white, + hover: ColorSchemeConstants.lightHover, + selector: ColorSchemeConstants.lightSelector, red: const Color(0xFFfb006d), yellow: const Color(0xFFFFd667), green: const Color(0xFF66cf80), - shader1: _lightShader1, + shader1: ColorSchemeConstants.lightShader1, shader2: const Color(0xFF4f4f4f), - shader3: _lightShader3, + shader3: ColorSchemeConstants.lightShader3, shader4: const Color(0xFFbdbdbd), - shader5: _lightShader5, - shader6: _lightShader6, - shader7: _lightShader1, - bg1: _lightBg1, - bg2: _lightBg2, + shader5: ColorSchemeConstants.lightShader5, + shader6: ColorSchemeConstants.lightShader6, + shader7: ColorSchemeConstants.lightShader1, + bg1: ColorSchemeConstants.lightBg1, + bg2: ColorSchemeConstants.lightBg2, bg3: const Color(0xFFe2e4eb), bg4: const Color(0xFF2c144b), tint1: const Color(0xFFe8e0FF), @@ -50,51 +54,54 @@ class DefaultColorScheme extends FlowyColorScheme { tint6: const Color(0xFFf5FFdc), tint7: const Color(0xFFddFFd6), tint8: const Color(0xFFdeFFf1), - tint9: _lightTint9, - main1: _lightMain1, + tint9: ColorSchemeConstants.lightTint9, + main1: ColorSchemeConstants.lightMain1, main2: const Color(0xFF00b7ea), shadow: const Color.fromRGBO(0, 0, 0, 0.15), - sidebarBg: _lightBg1, - divider: _lightShader6, - topbarBg: _white, - icon: _lightShader1, - text: _lightShader1, + sidebarBg: ColorSchemeConstants.lightBg1, + divider: ColorSchemeConstants.lightShader6, + topbarBg: ColorSchemeConstants.white, + icon: ColorSchemeConstants.lightShader1, + text: ColorSchemeConstants.lightShader1, secondaryText: const Color(0xFF4f4f4f), strongText: Colors.black, - input: _white, - hint: _lightShader3, - primary: _lightMain1, - onPrimary: _white, - hoverBG1: _lightBg2, - hoverBG2: _lightHover, - hoverBG3: _lightShader6, - hoverFG: _lightShader1, - questionBubbleBG: _lightSelector, - progressBarBGColor: _lightTint9, - toolbarColor: _lightShader1, - toggleButtonBGColor: _lightShader5, + input: ColorSchemeConstants.white, + hint: ColorSchemeConstants.lightShader3, + primary: ColorSchemeConstants.lightMain1, + onPrimary: ColorSchemeConstants.white, + hoverBG1: ColorSchemeConstants.lightBg2, + hoverBG2: ColorSchemeConstants.lightHover, + hoverBG3: ColorSchemeConstants.lightShader6, + hoverFG: ColorSchemeConstants.lightShader1, + questionBubbleBG: ColorSchemeConstants.lightSelector, + progressBarBGColor: ColorSchemeConstants.lightTint9, + toolbarColor: ColorSchemeConstants.lightShader1, + toggleButtonBGColor: ColorSchemeConstants.lightShader5, calendarWeekendBGColor: const Color(0xFFFBFBFC), - gridRowCountColor: _lightShader1, + gridRowCountColor: ColorSchemeConstants.lightShader1, + borderColor: ColorSchemeConstants.lightBorderColor, + scrollbarColor: const Color(0x3F171717), + scrollbarHoverColor: const Color(0x7F171717), ); const DefaultColorScheme.dark() : super( - surface: _darkShader2, - hover: _darkMain1, - selector: _darkShader2, + surface: ColorSchemeConstants.darkShader2, + hover: ColorSchemeConstants.darkMain1, + selector: ColorSchemeConstants.darkShader2, red: const Color(0xFFfb006d), yellow: const Color(0xFFF7CF46), green: const Color(0xFF66CF80), - shader1: _darkShader1, - shader2: _darkShader2, - shader3: _darkShader3, + shader1: ColorSchemeConstants.darkShader1, + shader2: ColorSchemeConstants.darkShader2, + shader3: ColorSchemeConstants.darkShader3, shader4: const Color(0xFF505469), - shader5: _darkShader5, - shader6: _darkShader6, - shader7: _white, + shader5: ColorSchemeConstants.darkShader5, + shader6: ColorSchemeConstants.darkShader6, + shader7: ColorSchemeConstants.white, bg1: const Color(0xFF1A202C), bg2: const Color(0xFFEDEEF2), - bg3: _darkMain1, + bg3: ColorSchemeConstants.darkMain1, bg4: const Color(0xFF2C144B), tint1: const Color(0x4d9327FF), tint2: const Color(0x66FC0088), @@ -105,29 +112,32 @@ class DefaultColorScheme extends FlowyColorScheme { tint7: const Color(0x5900BD2A), tint8: const Color(0x80008890), tint9: const Color(0x4d0029FF), - main1: _darkMain2, + main1: ColorSchemeConstants.darkMain2, main2: const Color(0xFF00B7EA), shadow: const Color(0xFF0F131C), sidebarBg: const Color(0xFF232B38), - divider: _darkShader3, - topbarBg: _darkShader1, - icon: _darkShader5, - text: _darkShader5, - secondaryText: _darkShader5, + divider: ColorSchemeConstants.darkShader3, + topbarBg: ColorSchemeConstants.darkShader1, + icon: ColorSchemeConstants.darkShader5, + text: ColorSchemeConstants.darkShader5, + secondaryText: ColorSchemeConstants.darkShader5, strongText: Colors.white, - input: _darkInput, + input: ColorSchemeConstants.darkInput, hint: const Color(0xFF59647a), - primary: _darkMain2, - onPrimary: _darkShader1, + primary: ColorSchemeConstants.darkMain2, + onPrimary: ColorSchemeConstants.darkShader1, hoverBG1: const Color(0x1AFFFFFF), - hoverBG2: _darkMain1, - hoverBG3: _darkShader3, + hoverBG2: ColorSchemeConstants.darkMain1, + hoverBG3: ColorSchemeConstants.darkShader3, hoverFG: const Color(0xE5FFFFFF), - questionBubbleBG: _darkShader3, - progressBarBGColor: _darkShader3, - toolbarColor: _darkInput, + questionBubbleBG: ColorSchemeConstants.darkShader3, + progressBarBGColor: ColorSchemeConstants.darkShader3, + toolbarColor: ColorSchemeConstants.darkInput, toggleButtonBGColor: const Color(0xFF828282), - calendarWeekendBGColor: _darkShader1, - gridRowCountColor: _darkShader5, + calendarWeekendBGColor: ColorSchemeConstants.darkShader1, + gridRowCountColor: ColorSchemeConstants.darkShader5, + borderColor: ColorSchemeConstants.darkBorderColor, + scrollbarColor: const Color(0x40FFFFFF), + scrollbarHoverColor: const Color(0x80FFFFFF), ); } diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart index 01eb66b02d..ddadc7302e 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart @@ -1,3 +1,4 @@ +import 'package:flowy_infra/colorscheme/default_colorscheme.dart'; import 'package:flutter/material.dart'; import 'colorscheme.dart'; @@ -77,6 +78,9 @@ class LavenderColorScheme extends FlowyColorScheme { toggleButtonBGColor: _lightSelector, calendarWeekendBGColor: const Color(0xFFFBFBFC), gridRowCountColor: _black, + borderColor: ColorSchemeConstants.lightBorderColor, + scrollbarColor: const Color(0x3F171717), + scrollbarHoverColor: const Color(0x7F171717), ); const LavenderColorScheme.dark() @@ -131,5 +135,8 @@ class LavenderColorScheme extends FlowyColorScheme { toggleButtonBGColor: _darkShader1, calendarWeekendBGColor: const Color(0xff121212), gridRowCountColor: _darkMain1, + borderColor: ColorSchemeConstants.darkBorderColor, + scrollbarColor: const Color(0x40FFFFFF), + scrollbarHoverColor: const Color(0x80FFFFFF), ); } diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lemonade.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lemonade.dart index 115de1e442..2bb6cb68c5 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lemonade.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lemonade.dart @@ -1,3 +1,4 @@ +import 'package:flowy_infra/colorscheme/default_colorscheme.dart'; import 'package:flutter/material.dart'; import 'colorscheme.dart'; @@ -83,6 +84,9 @@ class LemonadeColorScheme extends FlowyColorScheme { toggleButtonBGColor: _lightDandelionYellow, calendarWeekendBGColor: const Color(0xFFFBFBFC), gridRowCountColor: _black, + borderColor: ColorSchemeConstants.lightBorderColor, + scrollbarColor: const Color(0x3F171717), + scrollbarHoverColor: const Color(0x7F171717), ); const LemonadeColorScheme.dark() @@ -137,5 +141,8 @@ class LemonadeColorScheme extends FlowyColorScheme { toggleButtonBGColor: _darkShader1, calendarWeekendBGColor: const Color(0xff121212), gridRowCountColor: _darkMain1, + borderColor: ColorSchemeConstants.darkBorderColor, + scrollbarColor: const Color(0x40FFFFFF), + scrollbarHoverColor: const Color(0x80FFFFFF), ); } diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart index 48b4dfe86d..49195f2011 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart @@ -38,6 +38,9 @@ class AFThemeExtension extends ThemeExtension { required this.gridRowCountColor, required this.background, required this.onBackground, + required this.borderColor, + required this.scrollbarColor, + required this.scrollbarHoverColor, }); final Color? warning; @@ -74,6 +77,14 @@ class AFThemeExtension extends ThemeExtension { final Color background; final Color onBackground; + /// The color of the border of the widget. + /// + /// This is used in the divider, outline border, etc. + final Color borderColor; + + final Color scrollbarColor; + final Color scrollbarHoverColor; + @override AFThemeExtension copyWith({ Color? warning, @@ -105,6 +116,9 @@ class AFThemeExtension extends ThemeExtension { TextStyle? caption, Color? background, Color? onBackground, + Color? borderColor, + Color? scrollbarColor, + Color? scrollbarHoverColor, }) => AFThemeExtension( warning: warning ?? this.warning, @@ -137,6 +151,9 @@ class AFThemeExtension extends ThemeExtension { caption: caption ?? this.caption, onBackground: onBackground ?? this.onBackground, background: background ?? this.background, + borderColor: borderColor ?? this.borderColor, + scrollbarColor: scrollbarColor ?? this.scrollbarColor, + scrollbarHoverColor: scrollbarHoverColor ?? this.scrollbarHoverColor, ); @override @@ -188,6 +205,10 @@ class AFThemeExtension extends ThemeExtension { caption: other.caption, onBackground: Color.lerp(onBackground, other.onBackground, t)!, background: Color.lerp(background, other.background, t)!, + borderColor: Color.lerp(borderColor, other.borderColor, t)!, + scrollbarColor: Color.lerp(scrollbarColor, other.scrollbarColor, t)!, + scrollbarHoverColor: + Color.lerp(scrollbarHoverColor, other.scrollbarHoverColor, t)!, ); } } diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart index bbdeda8de3..92e459937e 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart @@ -12,7 +12,9 @@ export 'src/flowy_overlay/option_overlay.dart'; export 'src/keyboard/keyboard_visibility_detector.dart'; export 'style_widget/button.dart'; export 'style_widget/color_picker.dart'; +export 'style_widget/divider.dart'; export 'style_widget/icon_button.dart'; +export 'style_widget/scrollbar.dart'; export 'style_widget/scrolling/styled_list.dart'; export 'style_widget/scrolling/styled_scroll_bar.dart'; export 'style_widget/text.dart'; diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart index 3014d393dd..0564fc2a2f 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart @@ -1,5 +1,5 @@ import 'package:appflowy_popover/appflowy_popover.dart'; -import 'package:flowy_infra_ui/style_widget/decoration.dart'; +import 'package:flowy_infra/colorscheme/default_colorscheme.dart'; import 'package:flutter/material.dart'; class AppFlowyPopover extends StatelessWidget { @@ -17,7 +17,8 @@ class AppFlowyPopover extends StatelessWidget { final bool asBarrier; final EdgeInsets margin; final EdgeInsets windowPadding; - final Decoration? decoration; + final Color? decorationColor; + final BorderRadius? borderRadius; /// The widget that will be used to trigger the popover. /// @@ -46,9 +47,10 @@ class AppFlowyPopover extends StatelessWidget { this.asBarrier = false, this.margin = const EdgeInsets.all(6), this.windowPadding = const EdgeInsets.all(8.0), - this.decoration, this.clickHandler = PopoverClickHandler.listener, this.skipTraversal = false, + this.decorationColor, + this.borderRadius, }); @override @@ -70,7 +72,8 @@ class AppFlowyPopover extends StatelessWidget { return _PopoverContainer( constraints: constraints, margin: margin, - decoration: decoration, + decorationColor: decorationColor, + borderRadius: borderRadius, child: popupBuilder(context), ); }, @@ -81,33 +84,79 @@ class AppFlowyPopover extends StatelessWidget { class _PopoverContainer extends StatelessWidget { const _PopoverContainer({ + this.decorationColor, + this.borderRadius, required this.child, required this.margin, required this.constraints, - required this.decoration, }); final Widget child; final BoxConstraints constraints; final EdgeInsets margin; - final Decoration? decoration; + final Color? decorationColor; + final BorderRadius? borderRadius; @override Widget build(BuildContext context) { - final decoration = this.decoration ?? - FlowyDecoration.decoration( - Theme.of(context).cardColor, - Theme.of(context).colorScheme.shadow, - ); - return Material( type: MaterialType.transparency, child: Container( padding: margin, - decoration: decoration, + decoration: context.getPopoverDecoration( + color: decorationColor, + borderRadius: borderRadius, + ), constraints: constraints, child: child, ), ); } } + +extension on BuildContext { + /// The decoration of the popover. + /// + /// Don't customize the entire decoration of the popover, + /// use the built-in popoverDecoration instead and ask the designer before changing it. + ShapeDecoration getPopoverDecoration({ + Color? color, + BorderRadius? borderRadius, + }) { + final borderColor = Theme.of(this).brightness == Brightness.light + ? ColorSchemeConstants.lightBorderColor + : ColorSchemeConstants.darkBorderColor; + final shadows = [ + const BoxShadow( + color: Color(0x0A1F2329), + blurRadius: 24, + offset: Offset(0, 8), + spreadRadius: 8, + ), + const BoxShadow( + color: Color(0x0A1F2329), + blurRadius: 12, + offset: Offset(0, 6), + spreadRadius: 0, + ), + const BoxShadow( + color: Color(0x0F1F2329), + blurRadius: 8, + offset: Offset(0, 4), + spreadRadius: -8, + ) + ]; + return ShapeDecoration( + color: color ?? Theme.of(this).cardColor, + shape: RoundedRectangleBorder( + side: BorderSide( + width: 1, + strokeAlign: BorderSide.strokeAlignOutside, + color: borderColor, + ), + borderRadius: borderRadius ?? BorderRadius.circular(10), + ), + shadows: shadows, + ); + } +} diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart index e5649961fc..45bd218268 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -1,13 +1,141 @@ import 'dart:io'; -import 'package:flutter/material.dart'; - import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; import 'package:flowy_infra_ui/widget/ignore_parent_gesture.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; + +class FlowyIconTextButton extends StatelessWidget { + final Widget Function(bool onHover) textBuilder; + final VoidCallback? onTap; + final VoidCallback? onSecondaryTap; + final void Function(bool)? onHover; + final EdgeInsets? margin; + final Widget Function(bool onHover)? leftIconBuilder; + final Widget Function(bool onHover)? rightIconBuilder; + final Color? hoverColor; + final bool isSelected; + final BorderRadius? radius; + final BoxDecoration? decoration; + final bool useIntrinsicWidth; + final bool disable; + final double disableOpacity; + final Size? leftIconSize; + final bool expandText; + final MainAxisAlignment mainAxisAlignment; + final bool showDefaultBoxDecorationOnMobile; + final double iconPadding; + final bool expand; + final Color? borderColor; + + const FlowyIconTextButton({ + super.key, + required this.textBuilder, + this.onTap, + this.onSecondaryTap, + this.onHover, + this.margin, + this.leftIconBuilder, + this.rightIconBuilder, + this.hoverColor, + this.isSelected = false, + this.radius, + this.decoration, + this.useIntrinsicWidth = false, + this.disable = false, + this.disableOpacity = 0.5, + this.leftIconSize = const Size.square(16), + this.expandText = true, + this.mainAxisAlignment = MainAxisAlignment.center, + this.showDefaultBoxDecorationOnMobile = false, + this.iconPadding = 6, + this.expand = false, + this.borderColor, + }); + + @override + Widget build(BuildContext context) { + final color = hoverColor ?? Theme.of(context).colorScheme.secondary; + + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: disable ? null : onTap, + onSecondaryTap: disable ? null : onSecondaryTap, + child: FlowyHover( + cursor: + disable ? SystemMouseCursors.forbidden : SystemMouseCursors.click, + style: HoverStyle( + borderRadius: radius ?? Corners.s6Border, + hoverColor: color, + borderColor: borderColor ?? Colors.transparent, + ), + onHover: disable ? null : onHover, + isSelected: () => isSelected, + builder: (context, onHover) => _render(context, onHover), + ), + ); + } + + Widget _render(BuildContext context, bool onHover) { + final List children = []; + + if (leftIconBuilder != null) { + children.add( + SizedBox.fromSize( + size: leftIconSize, + child: leftIconBuilder!(onHover), + ), + ); + children.add(HSpace(iconPadding)); + } + + if (expandText) { + children.add(Expanded(child: textBuilder(onHover))); + } else { + children.add(textBuilder(onHover)); + } + + if (rightIconBuilder != null) { + children.add(HSpace(iconPadding)); + // No need to define the size of rightIcon. Just use its intrinsic width + children.add(rightIconBuilder!(onHover)); + } + + Widget child = Row( + mainAxisAlignment: mainAxisAlignment, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: expand ? MainAxisSize.max : MainAxisSize.min, + children: children, + ); + + if (useIntrinsicWidth) { + child = IntrinsicWidth(child: child); + } + + final decoration = this.decoration ?? + (showDefaultBoxDecorationOnMobile && + (Platform.isIOS || Platform.isAndroid) + ? BoxDecoration( + border: Border.all( + color: borderColor ?? + Theme.of(context).colorScheme.surfaceContainerHighest, + width: 1.0, + )) + : null); + + return Container( + decoration: decoration, + child: Padding( + padding: + margin ?? const EdgeInsets.symmetric(horizontal: 6, vertical: 4), + child: child, + ), + ); + } +} class FlowyButton extends StatelessWidget { final Widget text; @@ -30,6 +158,7 @@ class FlowyButton extends StatelessWidget { final bool showDefaultBoxDecorationOnMobile; final double iconPadding; final bool expand; + final Color? borderColor; const FlowyButton({ super.key, @@ -53,6 +182,7 @@ class FlowyButton extends StatelessWidget { this.showDefaultBoxDecorationOnMobile = false, this.iconPadding = 6, this.expand = false, + this.borderColor, }); @override @@ -80,6 +210,7 @@ class FlowyButton extends StatelessWidget { style: HoverStyle( borderRadius: radius ?? Corners.s6Border, hoverColor: color, + borderColor: borderColor ?? Colors.transparent, ), onHover: disable ? null : onHover, isSelected: () => isSelected, @@ -129,7 +260,8 @@ class FlowyButton extends StatelessWidget { (Platform.isIOS || Platform.isAndroid) ? BoxDecoration( border: Border.all( - color: Theme.of(context).colorScheme.surfaceContainerHighest, + color: borderColor ?? + Theme.of(context).colorScheme.surfaceContainerHighest, width: 1.0, )) : null); diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/decoration.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/decoration.dart index 0902d78835..a3f80cb41c 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/decoration.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/decoration.dart @@ -8,6 +8,7 @@ class FlowyDecoration { double blurRadius = 20, Offset offset = Offset.zero, double borderRadius = 6, + BoxBorder? border, }) { return BoxDecoration( color: boxColor, @@ -20,6 +21,7 @@ class FlowyDecoration { offset: offset, ), ], + border: border, ); } } diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/divider.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/divider.dart new file mode 100644 index 0000000000..d53362dbdb --- /dev/null +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/divider.dart @@ -0,0 +1,17 @@ +import 'package:flowy_infra/theme_extension.dart'; +import 'package:flutter/material.dart'; + +class FlowyDivider extends StatelessWidget { + const FlowyDivider({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Divider( + height: 1.0, + thickness: 1.0, + color: AFThemeExtension.of(context).borderColor, + ); + } +} diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrollbar.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrollbar.dart new file mode 100644 index 0000000000..01111293ec --- /dev/null +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrollbar.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +class FlowyScrollbar extends StatefulWidget { + const FlowyScrollbar({ + super.key, + this.controller, + required this.child, + }); + + final ScrollController? controller; + final Widget child; + + @override + State createState() => _FlowyScrollbarState(); +} + +class _FlowyScrollbarState extends State { + final ValueNotifier isHovered = ValueNotifier(false); + + @override + void dispose() { + isHovered.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return MouseRegion( + onEnter: (_) => isHovered.value = true, + onExit: (_) => isHovered.value = false, + child: ValueListenableBuilder( + valueListenable: isHovered, + builder: (context, isHovered, child) { + return Scrollbar( + thumbVisibility: isHovered, + // the radius should be fixed to 12 + radius: const Radius.circular(12), + controller: widget.controller, + child: ScrollConfiguration( + behavior: ScrollConfiguration.of(context).copyWith( + scrollbars: false, + ), + child: child!, + ), + ); + }, + child: widget.child, + ), + ); + } +} diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart index da22674152..ece1801098 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart @@ -1,12 +1,11 @@ import 'dart:async'; import 'dart:math'; -import 'package:flutter/material.dart'; - import 'package:async/async.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/widget/mouse_hover_builder.dart'; +import 'package:flutter/material.dart'; import 'package:styled_widget/styled_widget.dart'; class StyledScrollbar extends StatefulWidget { @@ -120,11 +119,6 @@ class ScrollbarState extends State { ? false : contentExtent > _viewExtent && contentExtent > 0; - // Handle color - var handleColor = widget.handleColor ?? - (Theme.of(context).brightness == Brightness.dark - ? AFThemeExtension.of(context).lightGreyHover - : AFThemeExtension.of(context).greyHover); // Track color var trackColor = widget.trackColor ?? (Theme.of(context).brightness == Brightness.dark @@ -161,18 +155,24 @@ class ScrollbarState extends State { onHorizontalDragUpdate: _handleHorizontalDrag, // HANDLE SHAPE child: MouseHoverBuilder( - builder: (_, isHovered) => Container( - width: widget.axis == Axis.vertical - ? widget.size - : handleExtent, - height: widget.axis == Axis.horizontal - ? widget.size - : handleExtent, - decoration: BoxDecoration( - color: handleColor.withOpacity(isHovered ? 1 : .85), - borderRadius: Corners.s3Border, - ), - ), + builder: (_, isHovered) { + final handleColor = + Theme.of(context).scrollbarTheme.thumbColor?.resolve( + isHovered ? {WidgetState.dragged} : {}, + ); + return Container( + width: widget.axis == Axis.vertical + ? widget.size + : handleExtent, + height: widget.axis == Axis.horizontal + ? widget.size + : handleExtent, + decoration: BoxDecoration( + color: handleColor, + borderRadius: Corners.s3Border, + ), + ); + }, ), ), ) diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text.dart index a4768969af..d624e83f09 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; - import 'package:google_fonts/google_fonts.dart'; class FlowyText extends StatelessWidget { @@ -20,6 +19,7 @@ class FlowyText extends StatelessWidget { final bool withTooltip; final StrutStyle? strutStyle; final bool isEmoji; + final double? figmaLineHeight; const FlowyText( this.text, { @@ -38,6 +38,7 @@ class FlowyText extends StatelessWidget { this.withTooltip = false, this.isEmoji = false, this.strutStyle, + this.figmaLineHeight, }); FlowyText.small( @@ -55,6 +56,7 @@ class FlowyText extends StatelessWidget { this.withTooltip = false, this.isEmoji = false, this.strutStyle, + this.figmaLineHeight, }) : fontWeight = FontWeight.w400, fontSize = (Platform.isIOS || Platform.isAndroid) ? 14 : 12; @@ -74,6 +76,7 @@ class FlowyText extends StatelessWidget { this.withTooltip = false, this.isEmoji = false, this.strutStyle, + this.figmaLineHeight, }) : fontWeight = FontWeight.w400; const FlowyText.medium( @@ -92,6 +95,7 @@ class FlowyText extends StatelessWidget { this.withTooltip = false, this.isEmoji = false, this.strutStyle, + this.figmaLineHeight, }) : fontWeight = FontWeight.w500; const FlowyText.semibold( @@ -110,6 +114,7 @@ class FlowyText extends StatelessWidget { this.withTooltip = false, this.isEmoji = false, this.strutStyle, + this.figmaLineHeight, }) : fontWeight = FontWeight.w600; // Some emojis are not supported on Linux and Android, fallback to noto color emoji @@ -128,6 +133,7 @@ class FlowyText extends StatelessWidget { this.strutStyle = const StrutStyle(forceStrutHeight: true), this.isEmoji = true, this.fontFamily, + this.figmaLineHeight, }) : fontWeight = FontWeight.w400, fallbackFontFamily = null; @@ -150,6 +156,13 @@ class FlowyText extends StatelessWidget { fontSize = fontSize * 0.8; } + double? lineHeight; + if (this.lineHeight != null) { + lineHeight = this.lineHeight!; + } else if (figmaLineHeight != null) { + lineHeight = figmaLineHeight! / fontSize; + } + final textStyle = Theme.of(context).textTheme.bodyMedium!.copyWith( fontSize: fontSize, fontWeight: fontWeight, diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/flowy_tooltip.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/flowy_tooltip.dart index 1eb8bd0046..960b8b3ad4 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/flowy_tooltip.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/flowy_tooltip.dart @@ -26,21 +26,47 @@ class FlowyTooltip extends StatelessWidget { return child ?? const SizedBox.shrink(); } - final isLightMode = Theme.of(context).brightness == Brightness.light; return Tooltip( margin: margin, verticalOffset: 16.0, - padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0), + padding: const EdgeInsets.only( + left: 12.0, + right: 12.0, + top: 5.0, + bottom: 8.0, + ), decoration: BoxDecoration( - color: isLightMode ? const Color(0xE5171717) : const Color(0xE5E5E5E5), - borderRadius: BorderRadius.circular(8.0), + color: context.tooltipBackgroundColor(), + borderRadius: BorderRadius.circular(12.0), ), waitDuration: _tooltipWaitDuration, message: message, + textStyle: message != null ? context.tooltipTextStyle() : null, richMessage: richMessage, - showDuration: showDuration, preferBelow: preferBelow, child: child, ); } } + +extension FlowyToolTipExtension on BuildContext { + double tooltipFontSize() => 13.0; + double tooltipHeight() => 18.0 / tooltipFontSize(); + Color tooltipFontColor() => Theme.of(this).brightness == Brightness.light + ? Colors.white + : Colors.black; + + TextStyle? tooltipTextStyle({Color? fontColor}) { + return Theme.of(this).textTheme.bodyMedium?.copyWith( + color: fontColor ?? tooltipFontColor(), + fontSize: tooltipFontSize(), + fontWeight: FontWeight.w400, + height: tooltipHeight(), + ); + } + + Color tooltipBackgroundColor() => + Theme.of(this).brightness == Brightness.light + ? const Color(0xFF1D2129) + : const Color(0xE5E5E5E5); +} diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 508d66dbb2..07f3dd331e 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.6.5 +version: 0.6.6 environment: flutter: ">=3.22.0" diff --git a/frontend/resources/flowy_icons/16x/favorite_section_pin.svg b/frontend/resources/flowy_icons/16x/favorite_section_pin.svg index 0402120e41..32b2466de4 100644 --- a/frontend/resources/flowy_icons/16x/favorite_section_pin.svg +++ b/frontend/resources/flowy_icons/16x/favorite_section_pin.svg @@ -1,5 +1,5 @@ - + diff --git a/frontend/resources/flowy_icons/16x/favorite_section_unpin.svg b/frontend/resources/flowy_icons/16x/favorite_section_unpin.svg index 3e72f90f4b..999adfa03b 100644 --- a/frontend/resources/flowy_icons/16x/favorite_section_unpin.svg +++ b/frontend/resources/flowy_icons/16x/favorite_section_unpin.svg @@ -1,5 +1,7 @@ - + + + diff --git a/frontend/resources/flowy_icons/16x/space_lock.svg b/frontend/resources/flowy_icons/16x/space_lock.svg index a048076b50..e5103e7de8 100644 --- a/frontend/resources/flowy_icons/16x/space_lock.svg +++ b/frontend/resources/flowy_icons/16x/space_lock.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index 30d5685319..5c91a45b47 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -272,7 +272,7 @@ "recent": "Recent", "today": "Today", "thisWeek": "This week", - "others": "Other favorites", + "others": "Earlier favorites", "justNow": "just now", "minutesAgo": "{count} minutes ago", "lastViewed": "Last viewed", @@ -2159,6 +2159,7 @@ "createNewSpace": "Create a new space", "createSpaceDescription": "Create multiple public and private spaces to better organize your work.", "spaceName": "Space name", + "spaceNamePlaceholder": "e.g. Marketing, Engineering, HR", "permission": "Permission", "publicPermission": "Public", "publicPermissionDescription": "All workspace members with full access",