Переглянути джерело

fix: hover color highlight with custom widget

appflowy 3 роки тому
батько
коміт
56ced4a76f

+ 5 - 10
app_flowy/lib/workspace/presentation/app/view_list.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/workspace/presentation/view/view_widget.dart';
 import 'package:flowy_infra/flowy_logger.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
-import 'package:flowy_infra_ui/style_widget/styled_hover.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:dartz/dartz.dart';
@@ -17,22 +16,18 @@ class ViewList extends StatelessWidget {
       () => const SizedBox(),
       (views) {
         return Column(
-          children: _renderViewWidgets(views),
+          children: _renderViews(views),
         );
       },
     );
   }
 
-  List<Widget> _renderViewWidgets(List<View> views) {
+  List<Widget> _renderViews(List<View> views) {
     var targetViews = views.map((view) {
       return Padding(
-        padding: const EdgeInsets.symmetric(vertical: 6),
-        child: StyledHover(
-          color: Colors.red,
-          borderRadius: BorderRadius.circular(8),
-          child: ViewWidget(
-            view: view,
-          ),
+        padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
+        child: ViewWidget(
+          view: view,
         ),
       );
     }).toList(growable: false);

+ 46 - 20
app_flowy/lib/workspace/presentation/view/view_widget.dart

@@ -5,6 +5,8 @@ import 'package:app_flowy/workspace/presentation/app/app_widget.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
 import 'package:flutter/material.dart';
+import 'package:flowy_infra_ui/style_widget/styled_more.dart';
+import 'package:flowy_infra_ui/style_widget/styled_hover.dart';
 
 class ViewWidget extends StatelessWidget {
   final View view;
@@ -12,32 +14,56 @@ class ViewWidget extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final contentPadding = EdgeInsets.only(
-        left: AppWidgetSize.expandedPadding, top: 5, bottom: 5, right: 5);
     return InkWell(
       onTap: _openView(context),
-      child: Padding(
-        padding: contentPadding,
-        child: buildContent(),
+      child: StyledHover(
+        color: Colors.grey.shade300,
+        borderRadius: BorderRadius.circular(8),
+        builder: (context, onHover) => _render(context, onHover),
       ),
     );
   }
 
-  Row buildContent() {
-    return Row(
-      children: [
-        Image(
-            fit: BoxFit.cover,
-            width: 20,
-            height: 20,
-            image: assetImageForViewType(view.viewType)),
-        const HSpace(6),
-        Text(
-          view.name,
-          textAlign: TextAlign.start,
-          style: const TextStyle(fontSize: 15),
-        )
-      ],
+  Widget _render(BuildContext context, bool onHover) {
+    const double width = 20;
+    List<Widget> children = [
+      Image(
+          fit: BoxFit.cover,
+          width: width,
+          height: width,
+          image: assetImageForViewType(view.viewType)),
+      const HSpace(6),
+      Text(
+        view.name,
+        textAlign: TextAlign.start,
+        style: const TextStyle(fontSize: 15),
+      ),
+    ];
+
+    if (onHover) {
+      children.add(const Spacer());
+
+      children.add(Align(
+        alignment: Alignment.center,
+        child: StyledMore(
+          width: width,
+          onPressed: () {},
+        ),
+      ));
+    }
+
+    final padding = EdgeInsets.only(
+      left: AppWidgetSize.expandedPadding,
+      top: 5,
+      bottom: 5,
+      right: 5,
+    );
+
+    return Padding(
+      padding: padding,
+      child: Flexible(
+        child: Row(children: children),
+      ),
     );
   }
 

+ 5 - 13
app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart

@@ -5,6 +5,8 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pbenum.dart';
 import 'package:flutter/material.dart';
+import 'package:flowy_infra_ui/style_widget/styled_more.dart';
+import 'package:flowy_infra_ui/style_widget/styled_text.dart';
 
 class HomeTopBar extends StatelessWidget {
   final HomeStackView view;
@@ -50,14 +52,9 @@ class HomeTopBar extends StatelessWidget {
   }
 
   Widget _renderMoreButton() {
-    return SizedBox(
+    return StyledMore(
       width: 24,
-      child: IconButton(
-        icon: const Icon(Icons.more_vert),
-        iconSize: 12,
-        alignment: Alignment.center,
-        onPressed: () {},
-      ),
+      onPressed: () {},
     );
   }
 }
@@ -83,12 +80,7 @@ class HomeTitle extends StatelessWidget {
               height: 15,
               image: assetImageForViewType(type)),
           const HSpace(6),
-          Text(
-            title,
-            overflow: TextOverflow.fade,
-            softWrap: false,
-            style: const TextStyle(fontSize: 16),
-          ),
+          StyledText(title, fontSize: 16),
         ],
       ),
     );

+ 2 - 6
app_flowy/lib/workspace/presentation/widgets/menu/menu_user.dart

@@ -5,6 +5,7 @@ import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flowy_infra_ui/style_widget/styled_text.dart';
 
 class MenuUser extends MenuItem {
   final UserDetail user;
@@ -44,12 +45,7 @@ class MenuUser extends MenuItem {
       name = context.read<MenuUserBloc>().state.user.email;
     }
     return Flexible(
-      child: Text(
-        name,
-        overflow: TextOverflow.fade,
-        softWrap: false,
-        style: const TextStyle(fontSize: 18),
-      ),
+      child: StyledText(name, fontSize: 18),
     );
   }
 

+ 34 - 35
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_hover.dart

@@ -1,59 +1,58 @@
-import 'package:flowy_infra_ui/widget/mouse_hover_builder.dart';
 import 'package:flutter/material.dart';
 import 'package:flowy_infra/time/duration.dart';
 
-class StyledHover extends StatelessWidget {
+typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
+
+class StyledHover extends StatefulWidget {
   final Color color;
   final Color borderColor;
   final double borderWidth;
-  final Widget child;
   final BorderRadius borderRadius;
+  final HoverBuilder builder;
 
   const StyledHover({
     Key? key,
     required this.color,
-    required this.child,
     this.borderColor = Colors.transparent,
     this.borderWidth = 0,
     this.borderRadius = BorderRadius.zero,
+    required this.builder,
   }) : super(key: key);
 
+  @override
+  State<StyledHover> createState() => _StyledHoverState();
+}
+
+class _StyledHoverState extends State<StyledHover> {
+  bool _onHover = false;
+
   @override
   Widget build(BuildContext context) {
-    return MouseHoverBuilder(
-      builder: (_, isHovered) => AnimatedContainer(
+    final hoverColor =
+        _onHover ? widget.color : Theme.of(context).colorScheme.background;
+
+    final hoverBorder = Border.all(
+      color: widget.borderColor,
+      width: widget.borderWidth,
+    );
+
+    final animatedDuration = .1.seconds;
+
+    return MouseRegion(
+      cursor: SystemMouseCursors.click,
+      onEnter: (p) => setOnHover(true),
+      onExit: (p) => setOnHover(false),
+      child: AnimatedContainer(
         decoration: BoxDecoration(
-          border: Border.all(color: borderColor, width: borderWidth),
-          color: isHovered ? color : Colors.transparent,
-          borderRadius: borderRadius,
+          border: hoverBorder,
+          color: hoverColor,
+          borderRadius: widget.borderRadius,
         ),
-        duration: .1.seconds,
-        child: child,
+        duration: animatedDuration,
+        child: widget.builder(context, _onHover),
       ),
     );
   }
-}
-
 
-// @override
-//   Widget build(BuildContext context) {
-//     return GestureDetector(
-//       behavior: HitTestBehavior.translucent,
-//       onTap: () {
-//         context
-//             .read<HomeBloc>()
-//             .add(HomeEvent.setEditPannel(CellEditPannelContext()));
-//       },
-//       child: MouseHoverBuilder(
-//         builder: (_, isHovered) => Container(
-//           width: width,
-//           decoration: CellDecoration.box(
-//             color: isHovered ? Colors.red.withOpacity(.1) : Colors.transparent,
-//           ),
-//           padding: EdgeInsets.symmetric(
-//               vertical: GridInsets.vertical, horizontal: GridInsets.horizontal),
-//           child: child,
-//         ),
-//       ),
-//     );
-//   }
+  void setOnHover(bool value) => setState(() => _onHover = value);
+}

+ 29 - 0
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_more.dart

@@ -0,0 +1,29 @@
+import 'package:flutter/material.dart';
+
+class StyledMore extends StatelessWidget {
+  final double width;
+  final double? height;
+  final VoidCallback? onPressed;
+
+  const StyledMore({
+    Key? key,
+    required this.width,
+    this.height,
+    this.onPressed,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return SizedBox(
+      width: width,
+      height: height ?? width,
+      child: IconButton(
+        icon: const Icon(Icons.more_vert),
+        padding: EdgeInsets.zero,
+        iconSize: width / 2,
+        alignment: Alignment.center,
+        onPressed: onPressed,
+      ),
+    );
+  }
+}

+ 23 - 0
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_text.dart

@@ -0,0 +1,23 @@
+import 'package:flutter/widgets.dart';
+
+class StyledText extends StatelessWidget {
+  final String title;
+  final TextOverflow overflow;
+  final double fontSize;
+  const StyledText(
+    this.title, {
+    Key? key,
+    this.overflow = TextOverflow.fade,
+    this.fontSize = 16,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Text(
+      title,
+      overflow: overflow,
+      softWrap: false,
+      style: TextStyle(fontSize: fontSize),
+    );
+  }
+}

+ 6 - 6
app_flowy/packages/flowy_infra_ui/lib/widget/mouse_hover_builder.dart

@@ -1,7 +1,7 @@
 import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
 
-typedef HoverBuilder = Widget Function(BuildContext context, bool isHovering);
+typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
 
 class MouseHoverBuilder extends StatefulWidget {
   final bool isClickable;
@@ -17,7 +17,7 @@ class MouseHoverBuilder extends StatefulWidget {
 }
 
 class _MouseHoverBuilderState extends State<MouseHoverBuilder> {
-  bool isOver = false;
+  bool _onHover = false;
 
   @override
   Widget build(BuildContext context) {
@@ -25,11 +25,11 @@ class _MouseHoverBuilderState extends State<MouseHoverBuilder> {
       cursor: widget.isClickable
           ? SystemMouseCursors.click
           : SystemMouseCursors.basic,
-      onEnter: (p) => setOver(true),
-      onExit: (p) => setOver(false),
-      child: widget.builder(context, isOver),
+      onEnter: (p) => setOnHover(true),
+      onExit: (p) => setOnHover(false),
+      child: widget.builder(context, _onHover),
     );
   }
 
-  void setOver(bool value) => setState(() => isOver = value);
+  void setOnHover(bool value) => setState(() => _onHover = value);
 }