import 'package:flutter/material.dart'; class HoverReliefWidget extends StatefulWidget { final Widget child; final VoidCallback? onPressed; final BorderRadius borderRadius; final double initialElevation; final double hoverElevation; final double scaleFactor; final bool enableHoverEffect; // Pour activer/désactiver l'effet de survol final Color initialShadowColor; // Nouveau paramètre final Color hoverShadowColor; // Nouveau paramètre const HoverReliefWidget({ required this.child, this.onPressed, this.borderRadius = const BorderRadius.all(Radius.circular(15.0)), this.initialElevation = 4.0, this.hoverElevation = 8.0, this.scaleFactor = 1.03, // Légèrement réduit par rapport à l'exemple précédent this.enableHoverEffect = true, // Par défaut, l'effet est activé this.initialShadowColor = const Color(0x26000000), // Default: Colors.black.withOpacity(0.15) this.hoverShadowColor = const Color(0x4D000000), // Default: Colors.black.withOpacity(0.3) super.key, }); @override State createState() => _HoverReliefWidgetState(); } class _HoverReliefWidgetState extends State { bool _isHovering = false; @override Widget build(BuildContext context) { final bool canHover = widget.enableHoverEffect && widget.onPressed != null; final hoverTransform = Matrix4.identity()..scale(widget.scaleFactor); final transform = _isHovering && canHover ? hoverTransform : Matrix4.identity(); final shadowColor = _isHovering && canHover ? widget.hoverShadowColor : widget.initialShadowColor; final elevation = _isHovering && canHover ? widget.hoverElevation : widget.initialElevation; Widget content = AnimatedContainer( duration: const Duration(milliseconds: 200), transform: transform, transformAlignment: Alignment.center, child: Material( color: Colors.transparent, elevation: elevation, shadowColor: shadowColor, borderRadius: widget.borderRadius, clipBehavior: Clip.antiAlias, child: widget.child, ), ); if (widget.onPressed == null) { // Si non cliquable, on retourne juste le contenu avec l'élévation initiale (pas de survol) // Ajustement: pour toujours avoir un Material de base même si non cliquable et sans hover. return Material( color: Colors.transparent, elevation: widget.initialElevation, // Utilise l'élévation initiale shadowColor: widget.initialShadowColor, // Appliqué ici pour l'état non cliquable borderRadius: widget.borderRadius, clipBehavior: Clip.antiAlias, child: widget.child, ); } return MouseRegion( onEnter: (_) { if (widget.enableHoverEffect) setState(() => _isHovering = true); }, onExit: (_) { if (widget.enableHoverEffect) setState(() => _isHovering = false); }, cursor: SystemMouseCursors.click, child: InkWell( onTap: widget.onPressed, borderRadius: widget.borderRadius, hoverColor: Colors.transparent, splashColor: Colors.grey.withOpacity(0.2), highlightColor: Colors.grey.withOpacity(0.1), child: content, ), ); } }