Skip to content
Blog

Mouse Hover Interactions in Flutter Desktop

Implement mouse hover effects in Flutter — from simple hover highlights to complex pointer tracking for desktop and web applications.

Published on • September 17, 2026

AI Assistant

The Missing Piece on Mobile

On mobile, there’s no hover state — users tap directly. On desktop, hover provides crucial feedback: buttons highlight, cards elevate, tooltips appear.

Flutter supports hover through MouseRegion and gesture detection.

MouseRegion: The Basic Hover

MouseRegion(
  onEnter: (event) => setState(() => _isHovered = true),
  onExit: (event) => setState(() => _isHovered = false),
  child: AnimatedContainer(
    duration: Duration(milliseconds: 200),
    padding: EdgeInsets.all(16),
    decoration: BoxDecoration(
      color: _isHovered ? Colors.blue.shade50 : Colors.white,
      borderRadius: BorderRadius.circular(8),
      boxShadow: _isHovered
          ? [BoxShadow(color: Colors.black12, blurRadius: 8)]
          : [],
    ),
    child: Text('Hover me'),
  ),
)

Cursor Changes

Change the cursor to indicate interactivity:

MouseRegion(
  cursor: SystemMouseCursors.click,
  child: MyButton(),
)

Available cursors:

  • SystemMouseCursors.click
  • SystemMouseCursors.move
  • SystemMouseCursors.resizeLeftRight
  • SystemMouseCursors.wait
  • SystemMouseCursors.forbidden

Reusable Hover Widget

Create a generic hover wrapper:

class HoverWidget extends StatefulWidget {
  final Widget child;
  final Widget Function(bool isHovered) builder;

  const HoverWidget({required this.child, required this.builder});

  @override
  State<HoverWidget> createState() => _HoverWidgetState();
}

class _HoverWidgetState extends State<HoverWidget> {
  bool _isHovered = false;

  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      onEnter: (_) => setState(() => _isHovered = true),
      onExit: (_) => setState(() => _isHovered = false),
      child: widget.builder(_isHovered),
    );
  }
}

// Usage
HoverWidget(
  child: MyCard(),
  builder: (isHovered) => AnimatedContainer(
    duration: Duration(milliseconds: 200),
    transform: Matrix4.identity()..scale(isHovered ? 1.02 : 1.0),
    child: MyCard(elevated: isHovered),
  ),
)

Position Tracking

For more advanced hover effects, track the pointer position:

MouseRegion(
  onHover: (event) {
    setState(() {
      _hoverPosition = event.localPosition;
    });
  },
  child: CustomPaint(
    painter: HoverHighlightPainter(_hoverPosition),
    child: MyWidget(),
  ),
)

Tooltips

Flutter’s built-in Tooltip widget uses hover automatically:

Tooltip(
  message: 'Click to save',
  child: IconButton(
    icon: Icon(Icons.save),
    onPressed: _save,
  ),
)

Best Practices

  1. Add hover to all interactive elements — buttons, links, cards
  2. Keep hover effects subtle — slight elevation, color shift, or scale
  3. Don’t rely solely on hover — it doesn’t exist on touch devices
  4. Use AnimatedContainer — smooth transitions look professional
  5. Test with different cursors — make sure the cursor communicates intent

Conclusion

Mouse hover is what makes desktop apps feel alive. With MouseRegion, you can add the polish that desktop users expect — hover highlights, cursor changes, and tooltip reveals that make your Flutter app feel truly native.