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
This commit is contained in:
Lucas.Xu 2024-07-26 09:49:13 +08:00 committed by GitHub
parent a2e211555e
commit 29fb4af40a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
54 changed files with 793 additions and 386 deletions

View File

@ -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"

View File

@ -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<MoveWindowDetector> {
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),
),
],
);

View File

@ -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<CalculateCell> {
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),
),
],
),

View File

@ -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);

View File

@ -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,
),

View File

@ -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,
),
],
);

View File

@ -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),
],

View File

@ -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<HomeSettingBloc>()
.add(const HomeSettingEvent.editPanelResizeStart()),
onHorizontalDragUpdate: (details) => context
.read<HomeSettingBloc>()
.add(HomeSettingEvent.editPanelResized(details.localPosition.dx)),
onHorizontalDragEnd: (details) => context
.read<HomeSettingBloc>()
.add(const HomeSettingEvent.editPanelResizeEnd()),
onHorizontalDragCancel: () => context
.read<HomeSettingBloc>()
.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),
],
);

View File

@ -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<HomeSettingBloc>()

View File

@ -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 {

View File

@ -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<int> switchToTheNextSpace = ValueNotifier(0);
ValueNotifier<int> 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<HomeHotKeys> {
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),
];

View File

@ -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: [

View File

@ -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),

View File

@ -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,

View File

@ -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),
),
],
);

View File

@ -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<MovePageMenu> {
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(

View File

@ -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<SidebarNewPageButton> createState() => _SidebarNewPageButtonState();
}
class _SidebarNewPageButtonState extends State<SidebarNewPageButton> {
@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<void> _createNewPage(BuildContext context) async {
Future<void> _createNewPage() async {
return createViewAndShowRenameDialogIfNeeded(
context,
LocaleKeys.newPageText.tr(),

View File

@ -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,
),
),
),
),

View File

@ -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);
}

View File

@ -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<CreateSpacePopup> {
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,
),
),
],

View File

@ -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<SpacePermissionSwitch> {
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<SpacePermissionSwitch> {
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<SpaceBloc>().state.isExpanded
? FlowySvgs.workspace_drop_down_menu_show_s
: FlowySvgs.workspace_drop_down_menu_hide_s,
),
],
),
),
const HSpace(4.0),
FlowySvg(
context.read<SpaceBloc>().state.isExpanded
? FlowySvgs.workspace_drop_down_menu_show_s
: FlowySvgs.workspace_drop_down_menu_hide_s,
),
],
);
if (onTapBlankArea != null) {

View File

@ -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<SidebarSpaceHeader> {
}
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),
),
],
);

View File

@ -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,

View File

@ -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');
}
}

View File

@ -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<SpaceIconPopup> {
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,

View File

@ -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,
),
),
),
);

View File

@ -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');
}
}

View File

@ -491,6 +491,7 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
final name = FlowyText.regular(
widget.view.name,
overflow: TextOverflow.ellipsis,
// figmaLineHeight: 18.0,
);
final children = [
const HSpace(2),

View File

@ -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,
),
);
}

View File

@ -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),
),
],
);

View File

@ -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,

View File

@ -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<T extends PopoverAction> extends StatefulWidget {
@ -54,7 +53,6 @@ class _PopoverActionListState<T extends PopoverAction>
@override
Widget build(BuildContext context) {
final child = widget.buildChild(popoverController);
return AppFlowyPopover(
asBarrier: widget.asBarrier,
controller: popoverController,

View File

@ -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<SidebarResizer> createState() => _SidebarResizerState();
}
class _SidebarResizerState extends State<SidebarResizer> {
final ValueNotifier<bool> isHovered = ValueNotifier(false);
final ValueNotifier<bool> 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<HomeSettingBloc>()
.add(const HomeSettingEvent.editPanelResizeStart());
},
onHorizontalDragUpdate: (details) {
isDragging.value = true;
context
.read<HomeSettingBloc>()
.add(HomeSettingEvent.editPanelResized(details.localPosition.dx));
},
onHorizontalDragEnd: (details) {
isDragging.value = false;
context
.read<HomeSettingBloc>()
.add(const HomeSettingEvent.editPanelResizeEnd());
},
onHorizontalDragCancel: () {
isDragging.value = false;
context
.read<HomeSettingBloc>()
.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,
);
},
);
},
),
),
);
}
}

View File

@ -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,
),
),

View File

@ -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<String, dynamic> json) =>
_$FlowyColorSchemeFromJson(json);

View File

@ -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),
);
}

View File

@ -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),
);
}

View File

@ -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),
);
}

View File

@ -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),
);
}

View File

@ -38,6 +38,9 @@ class AFThemeExtension extends ThemeExtension<AFThemeExtension> {
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<AFThemeExtension> {
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<AFThemeExtension> {
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<AFThemeExtension> {
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<AFThemeExtension> {
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)!,
);
}
}

View File

@ -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';

View File

@ -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,
);
}
}

View File

@ -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<Widget> 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);

View File

@ -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,
);
}
}

View File

@ -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,
);
}
}

View File

@ -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<FlowyScrollbar> createState() => _FlowyScrollbarState();
}
class _FlowyScrollbarState extends State<FlowyScrollbar> {
final ValueNotifier<bool> 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,
),
);
}
}

View File

@ -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<StyledScrollbar> {
? 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<StyledScrollbar> {
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,
),
);
},
),
),
)

View File

@ -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,

View File

@ -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);
}

View File

@ -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"

View File

@ -1,5 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.5">
<path d="M8.38274 2.1912C8.61919 1.95467 8.99451 1.91977 9.2623 2.18766L14.145 7.07205C14.3765 7.30363 14.411 7.68431 14.1468 7.94865C13.9854 8.11011 13.5919 8.23414 13.2876 7.92972L12.5611 7.20735L10.6204 9.1481C10.5628 9.20571 10.5477 9.30158 10.5477 9.38042L10.2799 13.2031C10.2799 13.285 10.2475 13.3638 10.1899 13.4214L9.84485 13.7657C9.60524 14.0063 9.21857 14.0071 8.98279 13.7713L6.20394 10.9936L3.37596 13.8224C3.1392 14.0592 2.75536 14.0592 2.51861 13.8224L2.5096 13.8134C2.27301 13.5767 2.27282 13.193 2.50916 12.9561L5.33522 10.1233L2.5568 7.34311C2.31101 7.09723 2.31763 6.71613 2.55769 6.47598L2.90214 6.13221C2.95976 6.07459 3.03787 6.04124 3.11932 6.04124L6.94541 5.77806C7.02695 5.77806 7.13094 5.77049 7.18854 5.71288L9.12891 3.77213L8.40493 3.04532C8.17437 2.81725 8.15367 2.42036 8.38274 2.1912Z" fill="#171717"/>
<path d="M4.21594 1C3.79948 1 3.53477 1.31897 3.53477 1.68668C3.53477 2.04293 3.85938 2.33534 4.21594 2.33333L5.34384 2.33534L5.3436 5.35268C5.3436 5.44225 5.26862 5.52899 5.20522 5.59239L2.43472 8.77204C2.37139 8.83537 2.33657 8.92204 2.33655 9.01163L2.33594 9.54668C2.33594 9.92001 2.62702 10.2214 3.00927 10.2214L7.33078 10.2221L7.33526 14.4C7.33563 14.7679 7.634 15 8.00193 15H8.01594C8.38412 15 8.68259 14.7682 8.6826 14.4L8.68275 10.223L13.0026 10.2213C13.3693 10.2213 13.6693 9.92001 13.6686 9.54668L13.6693 9.01078C13.6693 8.92122 13.6332 8.83471 13.5696 8.77107L10.8064 5.59145C10.7452 5.53017 10.6824 5.4439 10.6824 5.35433L10.6829 2.33676L11.8093 2.33334C12.2825 2.33334 12.492 1.93102 12.492 1.68001C12.492 1.26906 12.1693 1.00001 11.8093 1H4.21594ZM6.70711 2.33483L9.37687 2.33333L9.38048 5.94579L11.9314 8.89026L4.13249 8.88794L6.70923 5.93339L6.70711 2.33483Z" fill="#2B2F36"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 960 B

After

Width:  |  Height:  |  Size: 1019 B

View File

@ -1,5 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.5">
<path d="M9.2623 2.18766C8.99451 1.91977 8.61919 1.95467 8.38274 2.1912C8.15367 2.42036 8.17437 2.81725 8.40493 3.04532L9.12891 3.77213L7.18854 5.71288C7.13094 5.77049 7.02695 5.77806 6.94541 5.77806L3.11932 6.04124C3.03787 6.04124 2.95976 6.07459 2.90214 6.13221L2.55769 6.47598C2.31763 6.71613 2.31101 7.09723 2.5568 7.34311L5.33522 10.1233L2.50916 12.9561C2.27282 13.193 2.27301 13.5767 2.5096 13.8134L2.51861 13.8224C2.75536 14.0592 3.1392 14.0592 3.37596 13.8224L6.20394 10.9936L8.98279 13.7713C9.21857 14.0071 9.60524 14.0063 9.84485 13.7657L10.1899 13.4214C10.2475 13.3638 10.2799 13.285 10.2799 13.2031L10.5477 9.38042C10.5477 9.30159 10.5628 9.20571 10.6204 9.1481L12.5611 7.20735L13.2876 7.92972C13.5919 8.23414 13.9854 8.11011 14.1468 7.94865C14.411 7.68431 14.3765 7.30363 14.145 7.07205L9.2623 2.18766ZM10.0059 4.64872L11.7235 6.36508L9.40296 8.69111L9.14988 12.226L4.1365 7.20788L7.69325 6.96485L10.0059 4.64872Z" fill="#171717"/>
<path d="M2.42691 8.77204L4.58617 6.2939L5.54809 7.25582L4.12467 8.88794L7.18111 8.88885L8.67493 10.3827L8.67479 14.6208C8.67478 14.989 8.37631 15.2875 8.00813 15.2875H7.99411C7.62619 15.2875 7.32782 14.9894 7.32745 14.6215L7.32297 10.2221L3.00146 10.2214C2.61921 10.2214 2.32812 9.92001 2.32812 9.54668L2.32874 9.01163C2.32876 8.92204 2.36357 8.83537 2.42691 8.77204Z" fill="#171717"/>
<path d="M11.9236 8.89026L11.9012 8.89025L13.1997 10.1888C13.4669 10.1012 13.6613 9.8473 13.6608 9.54668L13.6615 9.01078C13.6615 8.92122 13.6254 8.83471 13.5618 8.77107L10.7986 5.59145C10.7374 5.53017 10.6746 5.4439 10.6746 5.35433L10.675 2.33675L11.8015 2.33334C12.2747 2.33334 12.4842 1.93102 12.4842 1.68001C12.4842 1.26906 12.1615 1.00001 11.8015 1H4.20813C4.14572 1 4.08673 1.00716 4.03152 1.02058L6.70009 3.68915L6.6993 2.33483L9.36906 2.33333L9.37267 5.94579L11.9236 8.89026Z" fill="#171717"/>
</g>
<path opacity="0.5" d="M1.79688 1.2002L14.1712 13.5746" stroke="#171717" stroke-width="1.2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,3 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M8.78714 4.75039V4.16515C8.78714 3.42984 8.6 1.25 5.99904 1.25C3.3 1.25 3.21094 3.42984 3.21094 4.16515V4.75039L3.38817 4.73529L3.2119 4.75123C2.30484 4.99873 2 5.7229 2 7.29041V8.20709C2 10.2238 2.50558 10.9996 4.14127 10.9996H7.85873C9.49442 10.9996 10 10.2238 10 8.20709V7.29041C10 5.7229 9.69516 4.99873 8.7881 4.75123L8.64331 4.73813L8.78714 4.75039ZM4.32618 4.16515V4.65048L7.6719 4.65039V4.16515C7.6719 3.0108 7.3 2.3002 5.99904 2.3002C4.65 2.3002 4.32618 3.0108 4.32618 4.16515ZM6.00078 8.95078C6.66352 8.95078 7.20078 8.41352 7.20078 7.75078C7.20078 7.08804 6.66352 6.55078 6.00078 6.55078C5.33804 6.55078 4.80078 7.08804 4.80078 7.75078C4.80078 8.41352 5.33804 8.95078 6.00078 8.95078Z" fill="#171717"/>
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M10.2465 5.5418V4.85902C10.2465 4.00116 10.0281 1.45801 6.99367 1.45801C3.84479 1.45801 3.74089 4.00116 3.74089 4.85902V5.5418L3.94766 5.52418L3.74201 5.54277C2.68377 5.83152 2.32812 6.67639 2.32812 8.50516V9.57461C2.32812 11.9274 2.91797 12.8326 4.82627 12.8326H9.16331C11.0716 12.8326 11.6615 11.9274 11.6615 9.57461V8.50516C11.6615 6.67639 11.3058 5.83152 10.2476 5.54277L10.0787 5.5275L10.2465 5.5418ZM5.042 4.85902V5.42523L8.94534 5.42513V4.85902C8.94534 3.51227 8.51146 2.68324 6.99367 2.68324C5.41979 2.68324 5.042 3.51227 5.042 4.85902ZM6.99115 10.4423C7.76434 10.4423 8.39115 9.81545 8.39115 9.04225C8.39115 8.26905 7.76434 7.64225 6.99115 7.64225C6.21795 7.64225 5.59115 8.26905 5.59115 9.04225C5.59115 9.81545 6.21795 10.4423 6.99115 10.4423Z" fill="#171717"/>
</svg>

Before

Width:  |  Height:  |  Size: 880 B

After

Width:  |  Height:  |  Size: 937 B

View File

@ -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",