129 lines
3.1 KiB
Dart
129 lines
3.1 KiB
Dart
// AUTO-GENERATED widget — matches web .btn
|
|
import 'package:flutter/material.dart';
|
|
import '../inou_theme.dart';
|
|
|
|
enum ButtonVariant { primary, secondary, danger }
|
|
enum ButtonSize { regular, small }
|
|
|
|
class InouButton extends StatelessWidget {
|
|
final String text;
|
|
final ButtonVariant variant;
|
|
final ButtonSize size;
|
|
final bool fullWidth;
|
|
final VoidCallback? onPressed;
|
|
final Widget? icon;
|
|
|
|
const InouButton({
|
|
super.key,
|
|
required this.text,
|
|
this.variant = ButtonVariant.primary,
|
|
this.size = ButtonSize.regular,
|
|
this.fullWidth = false,
|
|
this.onPressed,
|
|
this.icon,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final isSmall = size == ButtonSize.small;
|
|
final padding = isSmall
|
|
? const EdgeInsets.symmetric(horizontal: 12, vertical: 6)
|
|
: const EdgeInsets.symmetric(horizontal: 18, vertical: 10);
|
|
|
|
final style = _getStyle();
|
|
|
|
Widget button = TextButton(
|
|
onPressed: onPressed,
|
|
style: TextButton.styleFrom(
|
|
backgroundColor: style.background,
|
|
foregroundColor: style.foreground,
|
|
padding: padding,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: InouTheme.borderRadiusMd,
|
|
side: style.border,
|
|
),
|
|
textStyle: InouTheme.labelLarge.copyWith(
|
|
fontSize: isSmall ? 14 : 15,
|
|
),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
if (icon != null) ...[
|
|
icon!,
|
|
const SizedBox(width: 6),
|
|
],
|
|
Text(text),
|
|
],
|
|
),
|
|
);
|
|
|
|
if (fullWidth) {
|
|
button = SizedBox(width: double.infinity, child: button);
|
|
}
|
|
|
|
return button;
|
|
}
|
|
|
|
_ButtonStyle _getStyle() {
|
|
switch (variant) {
|
|
case ButtonVariant.primary:
|
|
return _ButtonStyle(
|
|
background: InouTheme.accent,
|
|
foreground: Colors.white,
|
|
border: BorderSide.none,
|
|
);
|
|
case ButtonVariant.secondary:
|
|
return _ButtonStyle(
|
|
background: InouTheme.bgCard,
|
|
foreground: InouTheme.text,
|
|
border: const BorderSide(color: InouTheme.border),
|
|
);
|
|
case ButtonVariant.danger:
|
|
return _ButtonStyle(
|
|
background: InouTheme.dangerLight,
|
|
foreground: InouTheme.danger,
|
|
border: BorderSide(color: InouTheme.danger.withOpacity(0.3)),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
class _ButtonStyle {
|
|
final Color background;
|
|
final Color foreground;
|
|
final BorderSide border;
|
|
|
|
_ButtonStyle({
|
|
required this.background,
|
|
required this.foreground,
|
|
required this.border,
|
|
});
|
|
}
|
|
|
|
/// Icon button (matches .btn-icon)
|
|
class InouIconButton extends StatelessWidget {
|
|
final IconData icon;
|
|
final VoidCallback? onPressed;
|
|
final Color? color;
|
|
|
|
const InouIconButton({
|
|
super.key,
|
|
required this.icon,
|
|
this.onPressed,
|
|
this.color,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return IconButton(
|
|
icon: Icon(icon),
|
|
onPressed: onPressed,
|
|
color: color ?? InouTheme.textSubtle,
|
|
iconSize: 20,
|
|
padding: const EdgeInsets.all(8),
|
|
constraints: const BoxConstraints(),
|
|
);
|
|
}
|
|
}
|