Free copy-paste Button 003 for Flutter: a ready-to-use button widget with full Dart source code and a live preview. Works on desktop. No external packages.
Copy the Dart code below into a new file in your Flutter project (for example lib/widgets/button_003.dart) and use the widget anywhere in your widget tree.
import 'package:flutter/material.dart';
class Button003 extends StatefulWidget {
const Button003({
super.key,
this.text = 'Explore',
this.tooltip = 'Quick Launch',
this.onPressed,
this.icon,
});
final String text;
final String tooltip;
final VoidCallback? onPressed;
final IconData? icon;
@override
State<Button003> createState() => _Button003State();
}
class _Button003State extends State<Button003> {
bool _isHovered = false;
bool _isPressed = false;
@override
Widget build(BuildContext context) {
const Color primaryAccent = Color(0xFF6366F1);
final Color textColor = _isPressed
? const Color(0xFF94A3B8)
: _isHovered
? Colors.white
: const Color(0xFFE2E8F0);
final Border border = _isPressed
? Border.all(color: primaryAccent.withValues(alpha: 0.3), width: 1.2)
: _isHovered
? Border.all(color: primaryAccent, width: 1.2)
: Border.all(color: const Color(0x29FFFFFF), width: 1.2);
final List<BoxShadow> shadows = _isHovered
? const [
BoxShadow(
color: Color(0x596366F1),
blurRadius: 18,
spreadRadius: 1,
offset: Offset(0, 4),
),
]
: const [
BoxShadow(
color: Color(0x66000000),
blurRadius: 10,
offset: Offset(0, 4),
),
];
return MouseRegion(
cursor: SystemMouseCursors.click,
onEnter: (_) => setState(() => _isHovered = true),
onExit: (_) => setState(() {
_isHovered = false;
_isPressed = false;
}),
child: Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
Positioned(
bottom: 68,
child: IgnorePointer(
ignoring: !_isHovered,
child: AnimatedOpacity(
opacity: _isHovered ? 1.0 : 0.0,
duration: const Duration(milliseconds: 200),
curve: Curves.easeOutCubic,
child: AnimatedSlide(
offset: _isHovered
? const Offset(0, 0)
: const Offset(0, 0.4),
duration: const Duration(milliseconds: 200),
curve: Curves.easeOutCubic,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 14,
vertical: 6,
),
decoration: BoxDecoration(
color: const Color(0xFF161622),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: const Color(0x3D6366F1),
width: 1,
),
boxShadow: const [
BoxShadow(
color: Color(0x80000000),
blurRadius: 12,
offset: Offset(0, 6),
),
],
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 6,
height: 6,
decoration: const BoxDecoration(
color: Color(0xFF818CF8),
shape: BoxShape.circle,
),
),
const SizedBox(width: 8),
Text(
widget.tooltip,
style: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
color: Color(0xFFC7D2FE),
letterSpacing: 0.4,
),
),
],
),
),
),
),
),
),
GestureDetector(
onTapDown: (_) => setState(() => _isPressed = true),
onTapUp: (_) {
setState(() => _isPressed = false);
widget.onPressed?.call();
},
onTapCancel: () {
if (_isPressed) setState(() => _isPressed = false);
},
child: AnimatedScale(
scale: _isPressed ? 0.96 : (_isHovered ? 1.02 : 1.0),
duration: const Duration(milliseconds: 140),
curve: Curves.easeOutCubic,
child: AnimatedContainer(
duration: const Duration(milliseconds: 180),
curve: Curves.easeOutCubic,
padding: const EdgeInsets.symmetric(
horizontal: 26,
vertical: 14,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: border,
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: _isPressed
? const [Color(0xFF0F0F15), Color(0xFF13131A)]
: _isHovered
? const [Color(0xFF1E1E2C), Color(0xFF151520)]
: const [Color(0xFF161620), Color(0xFF0F0F16)],
),
boxShadow: shadows,
),
child: widget.icon == null
? Text(
widget.text,
style: TextStyle(
color: textColor,
fontSize: 14,
fontWeight: FontWeight.w600,
letterSpacing: 0.5,
),
)
: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
widget.text,
style: TextStyle(
color: textColor,
fontSize: 14,
fontWeight: FontWeight.w600,
letterSpacing: 0.5,
),
),
const SizedBox(width: 8),
AnimatedSlide(
offset: _isHovered
? const Offset(0.15, 0)
: const Offset(0, 0),
duration: const Duration(milliseconds: 180),
child: Icon(
widget.icon,
size: 16,
color: textColor,
),
),
],
),
),
),
),
],
),
);
}
}