hover.dart 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import 'package:flutter/material.dart';
  2. // ignore: unused_import
  3. import 'package:flowy_infra/time/duration.dart';
  4. typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
  5. class FlowyHover extends StatefulWidget {
  6. final HoverDisplayConfig config;
  7. final HoverBuilder builder;
  8. const FlowyHover({
  9. Key? key,
  10. required this.builder,
  11. this.config = const HoverDisplayConfig(),
  12. }) : super(key: key);
  13. @override
  14. State<FlowyHover> createState() => _FlowyHoverState();
  15. }
  16. class _FlowyHoverState extends State<FlowyHover> {
  17. bool _onHover = false;
  18. @override
  19. Widget build(BuildContext context) {
  20. final hoverColor = _onHover
  21. ? widget.config.hoverColor
  22. : Theme.of(context).colorScheme.background;
  23. final config = widget.config.copyWith(hoverColor: hoverColor);
  24. return MouseRegion(
  25. cursor: SystemMouseCursors.click,
  26. onEnter: (p) => setOnHover(true),
  27. onExit: (p) => setOnHover(false),
  28. child: FlowyHoverBackground(
  29. config: config, child: widget.builder(context, _onHover)),
  30. );
  31. }
  32. void setOnHover(bool value) => setState(() => _onHover = value);
  33. }
  34. class HoverDisplayConfig {
  35. final Color borderColor;
  36. final double borderWidth;
  37. final Color? hoverColor;
  38. final BorderRadius borderRadius;
  39. const HoverDisplayConfig(
  40. {this.borderColor = Colors.transparent,
  41. this.borderWidth = 0,
  42. this.borderRadius = const BorderRadius.all(Radius.circular(8)),
  43. this.hoverColor});
  44. HoverDisplayConfig copyWith({Color? hoverColor}) {
  45. return HoverDisplayConfig(
  46. borderColor: borderColor,
  47. borderWidth: borderWidth,
  48. borderRadius: borderRadius,
  49. hoverColor: hoverColor);
  50. }
  51. }
  52. class FlowyHoverBackground extends StatelessWidget {
  53. final HoverDisplayConfig config;
  54. final Widget child;
  55. const FlowyHoverBackground({
  56. Key? key,
  57. required this.child,
  58. this.config = const HoverDisplayConfig(),
  59. }) : super(key: key);
  60. @override
  61. Widget build(BuildContext context) {
  62. final color = config.hoverColor ?? Theme.of(context).colorScheme.background;
  63. final hoverBorder = Border.all(
  64. color: config.borderColor,
  65. width: config.borderWidth,
  66. );
  67. return Container(
  68. decoration: BoxDecoration(
  69. border: hoverBorder,
  70. color: color,
  71. borderRadius: config.borderRadius,
  72. ),
  73. child: child,
  74. );
  75. }
  76. }