hover.dart 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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 ? widget.config.hoverColor : Theme.of(context).colorScheme.background;
  21. final config = widget.config.copyWith(hoverColor: hoverColor);
  22. return MouseRegion(
  23. cursor: SystemMouseCursors.click,
  24. onEnter: (p) => setOnHover(true),
  25. onExit: (p) => setOnHover(false),
  26. child: FlowyHoverBackground(config: config, child: widget.builder(context, _onHover)),
  27. );
  28. }
  29. void setOnHover(bool value) => setState(() => _onHover = value);
  30. }
  31. class HoverDisplayConfig {
  32. final Color borderColor;
  33. final double borderWidth;
  34. final Color? hoverColor;
  35. final BorderRadius borderRadius;
  36. const HoverDisplayConfig(
  37. {this.borderColor = Colors.transparent,
  38. this.borderWidth = 0,
  39. this.borderRadius = const BorderRadius.all(Radius.circular(6)),
  40. this.hoverColor});
  41. HoverDisplayConfig copyWith({Color? hoverColor}) {
  42. return HoverDisplayConfig(
  43. borderColor: borderColor,
  44. borderWidth: borderWidth,
  45. borderRadius: borderRadius,
  46. hoverColor: hoverColor,
  47. );
  48. }
  49. }
  50. class FlowyHoverBackground extends StatelessWidget {
  51. final HoverDisplayConfig config;
  52. final Widget child;
  53. const FlowyHoverBackground({
  54. Key? key,
  55. required this.child,
  56. this.config = const HoverDisplayConfig(),
  57. }) : super(key: key);
  58. @override
  59. Widget build(BuildContext context) {
  60. final color = config.hoverColor ?? Theme.of(context).colorScheme.background;
  61. final hoverBorder = Border.all(
  62. color: config.borderColor,
  63. width: config.borderWidth,
  64. );
  65. return Container(
  66. decoration: BoxDecoration(
  67. border: hoverBorder,
  68. color: color,
  69. borderRadius: config.borderRadius,
  70. ),
  71. child: child,
  72. );
  73. }
  74. }