Skip to content

Commit

Permalink
build button labels with a builder
Browse files Browse the repository at this point in the history
  • Loading branch information
mosberger committed Nov 29, 2023
1 parent 8cb0982 commit 25a1fba
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 63 deletions.
19 changes: 10 additions & 9 deletions lib/src/button/sbb_icon_text_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,14 @@ class _SBBIconTextButtonState extends State<SBBIconTextButton> {

@override
Widget build(BuildContext context) {
final style = SBBButtonStyles.of(context).iconTextStyle;
final buttonStyle = SBBButtonStyles.of(context);
final style = buttonStyle.iconTextStyle;
final isEnabled = widget.onPressed != null;
final textStyle = _isPressed || _hasFocus
? style?.textStyleHighlighted
: isEnabled
? style?.textStyle
: style?.textStyleDisabled;
return Semantics(
button: true,
child: SBBGroup(
Expand Down Expand Up @@ -83,15 +89,10 @@ class _SBBIconTextButtonState extends State<SBBIconTextButton> {
: style?.iconColorDisabled,
),
const SizedBox(height: 4.0),
Text(
buttonStyle.buttonLabelBuilder(
context,
widget.label,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: _isPressed || _hasFocus
? style?.textStyleHighlighted
: isEnabled
? style?.textStyle
: style?.textStyleDisabled,
style: textStyle,
),
],
),
Expand Down
51 changes: 20 additions & 31 deletions lib/src/button/sbb_primary_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@ import '../sbb_internal.dart';
class SBBPrimaryButton extends StatelessWidget {
const SBBPrimaryButton({
super.key,
this.label,
this.child,
required this.label,
this.isLoading = false,
required this.onPressed,
this.focusNode,
}) : assert(label != null && child == null || label == null && child != null);
});

final String? label;
final Widget? child;
final String label;
final bool isLoading;
final VoidCallback? onPressed;
final FocusNode? focusNode;
Expand All @@ -44,29 +42,31 @@ class SBBPrimaryButton extends StatelessWidget {
}

ElevatedButton _buildThemedMobile(BuildContext context) {
final styles = SBBButtonStyles.of(context);
return ElevatedButton(
style: SBBButtonStyles.of(context).primaryMobile,
style: styles.primaryMobile,
onPressed: isLoading ? null : onPressed,
focusNode: focusNode,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (isLoading) SBBLoadingIndicator.tinyCloud(),
if (label == null) child! else SBBButtonContent(label: label!),
styles.buttonLabelBuilder(context, label),
],
),
);
}

ElevatedButton _buildThemedWeb(BuildContext context) {
final styles = SBBButtonStyles.of(context);
return ElevatedButton(
style: SBBButtonStyles.of(context).primaryWebLean,
style: styles.primaryWebLean,
onPressed: onPressed,
focusNode: focusNode,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (label == null) child! else SBBButtonContent(label: label!),
styles.buttonLabelBuilder(context, label),
],
),
);
Expand Down Expand Up @@ -101,53 +101,42 @@ class SBBPrimaryButtonNegative extends StatelessWidget {

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
switch (SBBBaseStyle.of(context).hostPlatform) {
case HostPlatform.native:
return _buildThemedMobile(theme);
return _buildThemedMobile(context);
case HostPlatform.web:
return _buildThemedWeb(theme);
return _buildThemedWeb(context);
default:
return _buildThemedMobile(theme);
return _buildThemedMobile(context);
}
}

Widget _buildThemedMobile(ThemeData theme) {
Widget _buildThemedMobile(BuildContext context) {
final styles = SBBButtonStyles.of(context);
return ElevatedButton(
style: theme.extension<SBBButtonStyles>()?.primaryMobileNegative,
style: styles.primaryMobileNegative,
onPressed: isLoading ? null : onPressed,
focusNode: focusNode,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (isLoading) SBBLoadingIndicator.tinyCloud(),
Flexible(
child: Text(
label,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
styles.buttonLabelBuilder(context, label),
],
),
);
}

Widget _buildThemedWeb(ThemeData theme) {
Widget _buildThemedWeb(BuildContext context) {
final styles = SBBButtonStyles.of(context);
return ElevatedButton(
style: theme.extension<SBBButtonStyles>()?.primaryWebNegative,
style: styles.primaryWebNegative,
onPressed: onPressed,
focusNode: focusNode,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: Text(
label,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
styles.buttonLabelBuilder(context, label),
],
),
);
Expand Down
22 changes: 12 additions & 10 deletions lib/src/button/sbb_secondary_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,25 @@ import '../sbb_internal.dart';
class SBBSecondaryButton extends StatelessWidget {
const SBBSecondaryButton({
super. key,
this.label,
this.child,
required this.label,
this.isLoading = false,
required this.onPressed,
this.focusNode,
}) : assert(label != null && child == null || label == null && child != null);
});

final String? label;
final Widget? child;
final String label;
final bool isLoading;
final VoidCallback? onPressed;
final FocusNode? focusNode;

@override
Widget build(BuildContext context) {
final isWeb = SBBBaseStyle.of(context).hostPlatform == HostPlatform.web;
final style = SBBBaseStyle.of(context);
final isWeb = style.hostPlatform == HostPlatform.web;
final buttonStyles = SBBButtonStyles.of(context);
return OutlinedButton(
style: isWeb
? Theme.of(context).extension<SBBButtonStyles>()?.secondaryWebLean
? buttonStyles.secondaryWebLean
: Theme.of(context).outlinedButtonTheme.style?.copyWith(
// workaround for web
padding: SBBTheme.allStates(EdgeInsets.zero),
Expand All @@ -54,7 +53,7 @@ class SBBSecondaryButton extends StatelessWidget {
const SBBLoadingIndicator.tinySmoke(),
const SBBLoadingIndicator.tinyCement(),
),
if (label == null) child! else SBBButtonContent(label: label!),
buttonStyles.buttonLabelBuilder(context, label),
],
),
),
Expand All @@ -78,13 +77,16 @@ class SBBGhostButton extends StatelessWidget {
Widget build(BuildContext context) {
if (SBBBaseStyle.of(context).hostPlatform == HostPlatform.native)
debugPrint('WARNING: Ghost button should only be used for web platform.');
final styles = SBBButtonStyles.of(context);
return OutlinedButton(
style: Theme.of(context).extension<SBBButtonStyles>()?.ghostWebLean,
style: styles.ghostWebLean,
onPressed: onPressed,
focusNode: focusNode,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [SBBButtonContent(label: label)],
children: [
styles.buttonLabelBuilder(context, label),
],
),
);
}
Expand Down
17 changes: 6 additions & 11 deletions lib/src/button/sbb_tertiary_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,14 @@ import '../sbb_internal.dart';
class SBBTertiaryButtonLarge extends StatelessWidget {
const SBBTertiaryButtonLarge({
super.key,
this.label,
this.child,
required this.label,
this.icon,
this.isLoading = false,
required this.onPressed,
this.focusNode,
}) : assert(label != null && child == null || label == null && child != null);
});

final String? label;
final Widget? child;
final String label;
final IconData? icon;
final bool isLoading;
final VoidCallback? onPressed;
Expand All @@ -35,6 +33,7 @@ class SBBTertiaryButtonLarge extends StatelessWidget {
@override
Widget build(BuildContext context) {
final style = SBBBaseStyle.of(context);
final buttonStyles = SBBButtonStyles.of(context);
return TextButton(
style: Theme.of(context).textButtonTheme.style?.copyWith(
// workaround for web
Expand All @@ -58,7 +57,7 @@ class SBBTertiaryButtonLarge extends StatelessWidget {
padding: const EdgeInsetsDirectional.only(end: 4.0),
child: Icon(icon, size: sbbIconSizeSmall),
),
if (label == null) child! else SBBButtonContent(label: label!),
buttonStyles.buttonLabelBuilder(context, label),
],
),
),
Expand Down Expand Up @@ -124,11 +123,7 @@ class SBBTertiaryButtonSmall extends StatelessWidget {
padding: const EdgeInsetsDirectional.only(end: 4.0),
child: Icon(icon, size: sbbIconSizeSmall),
),
Text(
label,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
buttonStyle.buttonLabelBuilder(context, label),
],
),
),
Expand Down
5 changes: 4 additions & 1 deletion lib/src/sbb_internal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ class SBBInternal {
}

class SBBButtonContent extends StatelessWidget {
const SBBButtonContent({Key? key, required this.label}) : super(key: key);
const SBBButtonContent({Key? key, required this.label, this.style})
: super(key: key);

final String label;
final TextStyle? style;

@override
Widget build(BuildContext context) {
Expand All @@ -52,6 +54,7 @@ class SBBButtonContent extends StatelessWidget {
label,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: style,
),
);
}
Expand Down
21 changes: 20 additions & 1 deletion lib/src/theme/styles/src/sbb_button_styles.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import 'package:flutter/material.dart';
import '../../../sbb_internal.dart';
import '../sbb_styles.dart';

typedef ButtonLabelBuilder = Widget Function(
BuildContext context,
String label, {
TextStyle? style,
});

class SBBButtonStyles extends ThemeExtension<SBBButtonStyles> {
SBBButtonStyles({
this.primaryStyle,
Expand All @@ -17,6 +23,7 @@ class SBBButtonStyles extends ThemeExtension<SBBButtonStyles> {
this.iconSmallBorderlessStyle,
this.iconFormStyle,
this.iconTextStyle,
required this.buttonLabelBuilder,
});

factory SBBButtonStyles.$default({required SBBBaseStyle baseStyle}) => SBBButtonStyles(
Expand Down Expand Up @@ -154,8 +161,13 @@ class SBBButtonStyles extends ThemeExtension<SBBButtonStyles> {
iconColorHighlighted: baseStyle.defaultTextColor,
iconColorDisabled: SBBColors.metal,
),
buttonLabelBuilder: defaultButtonLabelBuilder,
);

static ButtonLabelBuilder defaultButtonLabelBuilder = (_, String label, { TextStyle? style }) {
return SBBButtonContent(label: label, style: style);
};

final SBBButtonStyle? primaryStyle;
final SBBButtonStyle? primaryNegativeStyle;
final SBBButtonStyle? secondaryStyle;
Expand All @@ -168,6 +180,7 @@ class SBBButtonStyles extends ThemeExtension<SBBButtonStyles> {
final SBBButtonStyle? iconSmallBorderlessStyle;
final SBBButtonStyle? iconFormStyle;
final SBBButtonStyle? iconTextStyle;
final ButtonLabelBuilder buttonLabelBuilder;

static SBBButtonStyles of(BuildContext context) => Theme.of(context).extension<SBBButtonStyles>()!;

Expand Down Expand Up @@ -211,6 +224,7 @@ class SBBButtonStyles extends ThemeExtension<SBBButtonStyles> {
SBBButtonStyle? iconSmallBorderlessStyle,
SBBButtonStyle? iconFormStyle,
SBBButtonStyle? iconTextStyle,
ButtonLabelBuilder? buttonLabelBuilder,
}) =>
SBBButtonStyles(
primaryStyle: primaryStyle ?? this.primaryStyle,
Expand All @@ -225,6 +239,7 @@ class SBBButtonStyles extends ThemeExtension<SBBButtonStyles> {
iconSmallBorderlessStyle: iconSmallBorderlessStyle ?? this.iconSmallBorderlessStyle,
iconFormStyle: iconFormStyle ?? this.iconFormStyle,
iconTextStyle: iconTextStyle ?? this.iconTextStyle,
buttonLabelBuilder: buttonLabelBuilder ?? this.buttonLabelBuilder,
);

@override
Expand All @@ -243,13 +258,16 @@ class SBBButtonStyles extends ThemeExtension<SBBButtonStyles> {
iconSmallBorderlessStyle: iconSmallBorderlessStyle?.lerp(other.iconSmallBorderlessStyle, t),
iconFormStyle: iconFormStyle?.lerp(other.iconFormStyle, t),
iconTextStyle: iconTextStyle?.lerp(other.iconTextStyle, t),
buttonLabelBuilder: other.buttonLabelBuilder,
);
}
}

extension ButtonStylesExtension on SBBButtonStyles? {
SBBButtonStyles merge(SBBButtonStyles? other) {
if (this == null) return other ?? SBBButtonStyles();
if (this == null) return other ?? SBBButtonStyles(
buttonLabelBuilder: SBBButtonStyles.defaultButtonLabelBuilder,
);
return this!.copyWith(
primaryStyle: this!.primaryStyle.merge(other?.primaryStyle),
primaryNegativeStyle: this!.primaryNegativeStyle.merge(other?.primaryNegativeStyle),
Expand All @@ -263,6 +281,7 @@ extension ButtonStylesExtension on SBBButtonStyles? {
iconSmallBorderlessStyle: this!.iconSmallBorderlessStyle.merge(other?.iconSmallBorderlessStyle),
iconFormStyle: this!.iconFormStyle.merge(other?.iconFormStyle),
iconTextStyle: this!.iconTextStyle.merge(other?.iconTextStyle),
buttonLabelBuilder: other?.buttonLabelBuilder ?? this!.buttonLabelBuilder,
) as SBBButtonStyles;
}
}

0 comments on commit 25a1fba

Please sign in to comment.