Button 007 — Flutter Button Widget

Free copy-paste Button 007 for Flutter: a ready-to-use button widget with full Dart source code and a live preview. Works on desktop. No external packages.

  • Category: Buttons
  • Platforms: desktop
  • Flutter SDK only — no external packages
  • Free to copy & use

How to use Button 007 in Flutter

Copy the Dart code below into a new file in your Flutter project (for example lib/widgets/button_007.dart) and use the widget anywhere in your widget tree.

Button 007 – Dart source code

import 'package:flutter/material.dart';

class Button007 extends StatefulWidget {
  const Button007({
    super.key,
    this.label = 'Hover me',
    this.onTap,
    this.activeColor = const Color(0xFF66FF66),
    this.baseColor = Colors.black,
    this.initialTextColor = const Color(0xFFF8F8FF),
    this.activeTextColor = Colors.black,
    this.fontSize = 17.0,
    this.padding = const EdgeInsets.symmetric(horizontal: 34, vertical: 15),
    this.duration = const Duration(milliseconds: 1000),
  });

  final String label;
  final VoidCallback? onTap;
  final Color activeColor;
  final Color baseColor;
  final Color initialTextColor;
  final Color activeTextColor;
  final double fontSize;
  final EdgeInsetsGeometry padding;
  final Duration duration;

  @override
  State<Button007> createState() => _Button007State();
}

class _Button007State extends State<Button007>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;
  late final Animation<double> _animation;
  bool _isPressed = false;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: widget.duration);
    _animation = CurvedAnimation(
      parent: _controller,
      curve: const Cubic(0.3, 1.0, 0.8, 1.0),
      reverseCurve: const Cubic(0.3, 1.0, 0.8, 1.0),
    );
  }

  @override
  void didUpdateWidget(covariant Button007 oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.duration != oldWidget.duration) {
      _controller.duration = widget.duration;
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _handleHover(bool isHovered) {
    if (isHovered) {
      _controller.forward();
    } else {
      _controller.reverse();
    }
  }

  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      cursor: SystemMouseCursors.click,
      onEnter: (_) => _handleHover(true),
      onExit: (_) => _handleHover(false),
      child: GestureDetector(
        onTapDown: (_) => setState(() => _isPressed = true),
        onTapUp: (_) {
          setState(() => _isPressed = false);
          widget.onTap?.call();
        },
        onTapCancel: () => setState(() => _isPressed = false),
        child: AnimatedScale(
          scale: _isPressed ? 0.96 : 1.0,
          duration: const Duration(milliseconds: 100),
          curve: Curves.easeOutCubic,
          child: ClipRRect(
            borderRadius: BorderRadius.circular(500),
            child: AnimatedBuilder(
              animation: _animation,
              builder: (context, child) {
                return CustomPaint(
                  painter: _SkewRevealPainter(
                    progress: _animation.value,
                    activeColor: widget.activeColor,
                    baseColor: widget.baseColor,
                  ),
                  child: Padding(
                    padding: widget.padding,
                    child: Text(
                      widget.label,
                      style: TextStyle(
                        color: Color.lerp(
                          widget.initialTextColor,
                          widget.activeTextColor,
                          _animation.value,
                        ),
                        fontSize: widget.fontSize,
                        fontWeight: FontWeight.w700,
                        letterSpacing: 0.85,
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      ),
    );
  }
}

class _SkewRevealPainter extends CustomPainter {
  const _SkewRevealPainter({
    this.progress = 0.0,
    this.activeColor = const Color(0xFF66FF66),
    this.baseColor = Colors.black,
  });

  final double progress;
  final Color activeColor;
  final Color baseColor;

  @override
  void paint(Canvas canvas, Size size) {
    final Rect fullRect = Offset.zero & size;
    canvas.drawRect(fullRect, Paint()..color = activeColor);

    final double slideOffset = size.width * 1.35 * progress;
    final double skewAmount = size.height * 0.65;

    final Path path = Path()
      ..moveTo(-size.width * 0.1 + slideOffset, 0)
      ..lineTo(size.width * 1.2 + slideOffset, 0)
      ..lineTo(size.width * 1.2 - skewAmount + slideOffset, size.height)
      ..lineTo(-size.width * 0.1 - skewAmount + slideOffset, size.height)
      ..close();

    canvas.drawPath(path, Paint()..color = baseColor);
  }

  @override
  bool shouldRepaint(_SkewRevealPainter oldDelegate) {
    return oldDelegate.progress != progress ||
        oldDelegate.activeColor != activeColor ||
        oldDelegate.baseColor != baseColor;
  }
}

More Flutter Buttons