inou/app/lib/design/widgets/inou_button.dart

130 lines
3.2 KiB
Dart

// AUTO-GENERATED widget — matches web .btn
import 'package:flutter/material.dart';
import 'package:inou_app/design/inou_theme.dart';
import 'package:inou_app/design/inou_text.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: InouText.label.copyWith(
fontSize: 15, // Always 15px (1rem) for both sizes per styleguide
),
),
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(),
);
}
}