Button
A customizable button component with text, optional icons, loading states, and comprehensive styling support
A customizable button component that supports text with optional icons, loading states, and styling.
When to use this
- Primary actions: Submit forms, confirm dialogs, save data, trigger main actions
- Navigation: Navigate between screens, open new views, switch contexts
- Trigger functions: Show modals, start processes, toggle features, execute commands
- Call to action: Encourage users to take important actions within your app
Basic implementation
Basic implementation
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
class ButtonExample extends StatelessWidget {
const ButtonExample({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 16,
children: [
RemixButton(
onPressed: () {},
label: 'Turn Off',
style: destructiveStyle,
),
RemixButton(
onPressed: () {},
label: 'Turn on',
style: successStyle,
),
],
),
);
}
ButtonStyler get destructiveStyle {
return ButtonStyler()
.padding(.horizontal(16))
.padding(.vertical(10))
.color(const Color(0xFF4D1919))
.shadow(
BoxShadowMix().color(Colors.redAccent).blurRadius(10).spreadRadius(0),
)
.label(
TextStyler().uppercase().color(Colors.redAccent),
)
.shape(.beveledRectangle(
borderRadius: BorderRadiusMix()
.bottomLeft(const Radius.circular(12))
.topRight(const Radius.circular(12)),
side: BorderSideMix.width(1).color(Colors.redAccent),
))
.wrap(.scale(x: 1, y: 1))
.onPressed(
.scale(0.90),
)
.onHovered(
.color(const Color(0xFF732D2D))
.animate(AnimationConfig.spring(300.ms)),
)
.onFocused(
.color(const Color(0xFF732D2D)),
);
}
ButtonStyler get successStyle {
return destructiveStyle
.color(const Color.fromARGB(255, 15, 61, 15))
.label(TextStyler().uppercase().color(Colors.greenAccent))
.shape(.beveledRectangle(
side: BorderSideMix().color(Colors.greenAccent),
))
.shadow(
BoxShadowMix()
.color(Colors.greenAccent)
.blurRadius(10)
.spreadRadius(0),
)
.onHovered(
.color(const Color(0xFF357857)),
)
.onFocused(
.color(const Color(0xFF357857)),
);
}
}Fortal widgets
The application-owned Fortal preset provides a themed widget for this component:
Fortal variants
import 'package:flutter/material.dart';
import 'ui/ui.dart';
class FortalButtonExample extends StatelessWidget {
const FortalButtonExample({super.key});
@override
Widget build(BuildContext context) {
return Column(
spacing: 16,
children: [
// Solid variant - High emphasis, primary actions
FortalButton.solid(
label: 'Solid Button',
onPressed: () {},
),
// Soft variant - Medium emphasis, secondary actions
FortalButton.soft(
label: 'Soft Button',
onPressed: () {},
),
// Surface variant - Subtle emphasis with border
FortalButton.surface(
label: 'Surface Button',
onPressed: () {},
),
// Outline variant - Low emphasis, tertiary actions
FortalButton.outline(
label: 'Outline Button',
onPressed: () {},
),
// Ghost variant - Minimal styling, inline actions
FortalButton.ghost(
label: 'Ghost Button',
onPressed: () {},
),
],
);
}
}See the fortalButtonStyle source code for all available options.
Fortal button icon sizing
FortalButton.size selects layout, label and default icon dimensions. Leading
and trailing icons share Fortal IconButton's token-based size scale:
space3, space4, spinnerSize3, and space5 for sizes 1 through 4.
The surrounding IconTheme no longer determines their size. Base
RemixButton remains theme-neutral and still supports inherited sizing.
For an explicit per-button override, customize the icon styler through
FortalButton(style: ButtonStyler().icon(IconStyler().size(14)), ...), or pass
a customized Fortal recipe to RemixButton as below. Applications previously
depending on IconTheme.size for Fortal buttons should use an explicit override.
Explicit Fortal icon size
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
import 'ui/ui.dart';
class FortalButtonIconSizeExample extends StatelessWidget {
const FortalButtonIconSizeExample({super.key});
@override
Widget build(BuildContext context) {
return FortalScope(
child: RemixButton(
label: 'Save',
leadingIcon: Icons.save,
trailingIcon: Icons.check,
onPressed: () {},
style: fortalButtonStyle(variant: .soft, size: .size1)
.icon(IconStyler().size(14)),
),
);
}
}The 14-pixel value is a caller choice, not a Fortal size preset. This override
applies to both default icon slots. Custom leadingIconBuilder and
trailingIconBuilder implementations receive the icon spec and are responsible
for applying it to their own widgets.
Constructor
Constructor
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
RemixButton remixButtonConstructor({
Key? key,
required String label,
IconData? leadingIcon,
IconData? trailingIcon,
RemixButtonTextBuilder? textBuilder,
RemixButtonIconBuilder? leadingIconBuilder,
RemixButtonIconBuilder? trailingIconBuilder,
RemixButtonLoadingBuilder? loadingBuilder,
bool loading = false,
bool enabled = true,
VoidCallback? onPressed,
VoidCallback? onLongPress,
FocusNode? focusNode,
bool autofocus = false,
bool enableFeedback = true,
String? semanticLabel,
String? semanticHint,
bool excludeSemantics = false,
MouseCursor mouseCursor = SystemMouseCursors.click,
ButtonStyler style = const ButtonStyler.create(),
ButtonSpec? styleSpec,
}) => throw UnimplementedError();Properties
Widget Properties
style → ButtonStyler
Optional. The style configuration for the button. Customize colors, sizing, spacing, and state-based styling.
styleSpec → ButtonSpec?
Optional. A pre-resolved style spec that bypasses style resolution. Useful for performance when sharing resolved styles across multiple instances.
key → Key?
Optional. Controls how one widget replaces another widget in the tree.
label → String
Required. The label text to display in the button. If [textBuilder] is provided, this is ignored.
leadingIcon → IconData?
Optional. The leading icon to display before the label. If [leadingIconBuilder] is provided, this is ignored.
trailingIcon → IconData?
Optional. The trailing icon to display after the label. If [trailingIconBuilder] is provided, this is ignored.
textBuilder → RemixButtonTextBuilder?
Optional. Builder for customizing the text rendering.
leadingIconBuilder → RemixButtonIconBuilder?
Optional. Builder for customizing the leading icon rendering.
trailingIconBuilder → RemixButtonIconBuilder?
Optional. Builder for customizing the trailing icon rendering.
loadingBuilder → RemixButtonLoadingBuilder?
Optional. Builder for customizing the loading state rendering.
autofocus → bool
Optional. Whether the button should automatically request focus when it is created.
loading → bool
Optional. Whether the button is in a loading state. When true, the button will display a spinner and become non-interactive. The spinner can be customized via [loadingBuilder].
enabled → bool
Optional. Whether the button is enabled. When false, the button will be disabled regardless of other conditions. Defaults to true.
enableFeedback → bool
Optional. Whether to provide feedback when the button is pressed. Defaults to true.
onPressed → VoidCallback?
Optional. Callback function called when the button is pressed. If null, the button will be considered disabled.
onLongPress → VoidCallback?
Optional. Callback function called when the button is long pressed.
focusNode → FocusNode?
Optional. Optional focus node to control the button's focus behavior.
semanticLabel → String?
Optional. The semantic label for the button. Used by screen readers to describe the button.
semanticHint → String?
Optional. The semantic hint for the button. Provides additional context about what will happen when the button is activated.
excludeSemantics → bool
Optional. Whether to exclude child semantics. When true, the semantics of child widgets will be excluded. Defaults to false.
mouseCursor → MouseCursor
Optional. Cursor when hovering over the button. Defaults to [SystemMouseCursors.click] when enabled.
Style Methods
container(FlexBoxStyler value)
Configures the button container style.
label(TextStyler value)
Configures the label text style using a TextStyler.
icon(IconStyler value)
Configures the icon style using an IconStyler.
spinner(SpinnerStyler value)
Configures the loading spinner style.
iconAlignment(RemixPlacement value)
Overrides placement when the button has exactly one icon. Buttons with both
leadingIcon and trailingIcon keep those explicit positions.
padding(EdgeInsetsGeometryMix value)
Sets padding
margin(EdgeInsetsGeometryMix value)
Sets margin
decoration(DecorationMix value)
Sets decoration
alignment(Alignment value)
Sets container alignment
spacing(double value)
Sets item spacing between icon and label (Flex spacing)
constraints(BoxConstraintsMix value)
Sets constraints
animate(AnimationConfig value)
Configures implicit animation for style transitions.
variants(List<VariantStyle<ButtonSpec>> value)
Sets style variants.
foregroundDecoration(DecorationMix value)
Sets a foreground decoration painted on top of the component.
transform(Matrix4 value, AlignmentGeometry alignment = Alignment.center)
Applies a matrix transformation to the component.
color(Color value)
Sets background color.
Set the label and icon color through their own slots:
.label(.color(value)).icon(.color(value)).
wrap(WidgetModifierConfig value)
Applies widget modifiers such as clipping, opacity, or scaling.
modifier(WidgetModifierConfig value)
Sets the widget modifier.
call({ ... })
Creates a RemixButton widget with this style applied.
labelStyle(TextStyleMix value)
Sets label/text style using TextStyleMix directly
labelColor(Color value)
Sets label/text color
labelFontSize(double value)
Sets label/text font size
labelFontWeight(FontWeight value)
Sets label/text font weight
labelFontStyle(FontStyle value)
Sets label/text font style (italic/normal)
labelLetterSpacing(double value)
Sets label/text letter spacing
labelDecoration(TextDecoration value)
Sets label/text decoration (underline, strikethrough, etc.)
labelFontFamily(String value)
Sets label/text font family
labelHeight(double value)
Sets label/text line height
labelWordSpacing(double value)
Sets label/text word spacing
labelDecorationColor(Color value)
Sets label/text decoration color
iconColor(Color value)
Sets icon color
iconSize(double value)
Sets icon size
iconOpacity(double value)
Sets icon opacity
iconWeight(double value)
Sets icon weight (useful for variable icons like Material Symbols)
iconGrade(double value)
Sets icon grade (useful for Material Icons)
iconFill(double value)
Sets icon fill (useful for Material Icons filled variants)
iconOpticalSize(double value)
Sets icon optical size (useful for Material Icons)
iconBlendMode(BlendMode value)
Sets icon blend mode
iconTextDirection(TextDirection value)
Sets icon text direction
iconShadows(List<ShadowMix> value)
Sets icon shadows
iconShadow(ShadowMix value)
Sets single icon shadow
spinnerIndicatorColor(Color value)
Sets spinner indicator color
spinnerTrackColor(Color value)
Sets spinner track color
spinnerSize(double value)
Sets spinner size
spinnerStrokeWidth(double value)
Sets spinner stroke width
spinnerTrackStrokeWidth(double value)
Sets spinner track stroke width
spinnerDuration(Duration value)
Sets spinner animation duration
spinnerFast()
Sets spinner animation to fast (500ms)
spinnerNormal()
Sets spinner animation to normal (1000ms)
spinnerSlow()
Sets spinner animation to slow (1500ms)
See the alignment API migration table for source-breaking type replacements.