diff --git a/.idea/runConfigurations/Forui_Example___run.xml b/.idea/runConfigurations/Forui_Example___run.xml
deleted file mode 100644
index 7c4a018bd..000000000
--- a/.idea/runConfigurations/Forui_Example___run.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations/dev.xml b/.idea/runConfigurations/docs___run.xml
similarity index 78%
rename from .idea/runConfigurations/dev.xml
rename to .idea/runConfigurations/docs___run.xml
index 87dae7612..e6ea3f5ff 100644
--- a/.idea/runConfigurations/dev.xml
+++ b/.idea/runConfigurations/docs___run.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/.idea/runConfigurations/forui___tests.xml b/.idea/runConfigurations/forui___tests.xml
new file mode 100644
index 000000000..9a7619973
--- /dev/null
+++ b/.idea/runConfigurations/forui___tests.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Update_Golden_Test_Images.xml b/.idea/runConfigurations/forui___update_golden_test_images.xml
similarity index 67%
rename from .idea/runConfigurations/Update_Golden_Test_Images.xml
rename to .idea/runConfigurations/forui___update_golden_test_images.xml
index bbfedd410..5f492b8c1 100644
--- a/.idea/runConfigurations/Update_Golden_Test_Images.xml
+++ b/.idea/runConfigurations/forui___update_golden_test_images.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/.idea/runConfigurations/samples___run.xml b/.idea/runConfigurations/samples___run.xml
new file mode 100644
index 000000000..2d69cd950
--- /dev/null
+++ b/.idea/runConfigurations/samples___run.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 594ce763a..c6e8eba6a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -97,41 +97,6 @@ They should:
5. implement `operator ==` and `hashCode`.
-Widget should not scale `TextStyle`S during initialization. `TextStyle`s should be scaled in a widget's build method instead.
-This avoids confusion about whether `TextStyle`s are automatically scaled inside widget styles.
-
-✅ Prefer this:
-```dart
-class FooStyle {
- final TextStyle text;
-
- FooStyle.inherit({FFont font, FColorScheme scheme}): text = const TextStyle(size: 1);
-}
-
-class Foo extends StatelessWidget {
- final FooStyle style;
-
- @overrride
- Widget build(BuildContext context) => Text('Hi', style: style.text.withFont(context.theme.font));
-}
-```
-
-❌ Instead of:
-```dart
-class FooStyle {
- final TextStyle text;
-
- FooStyle.inherit({FFont font, FColorScheme scheme}): text = const TextStyle(size: 1).withFont(font);
-}
-
-class Foo extends StatelessWidget {
- final FooStyle style;
-
- @overrride
- Widget build(BuildContext context) => Text('Hi', style: style.text);
-}
-```
-
## Expose `String` and `Widget` variants of the same parameter.
Widgets typically contain string-based content such as titles and labels. These widgets should expose a `String` and
diff --git a/forui/example/lib/main.dart b/forui/example/lib/main.dart
index 3d33cce5b..9556e881f 100644
--- a/forui/example/lib/main.dart
+++ b/forui/example/lib/main.dart
@@ -53,16 +53,16 @@ class _ExampleWidgetState extends State {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FButton(
- design: FButtonVariant.destructive,
+ style: FButtonStyle.destructive,
label: 'Delete?',
onPress: () => showAdaptiveDialog(
context: context,
builder: (context) => FDialog(
- alignment: FDialogAlignment.horizontal,
+ direction: Axis.horizontal,
title: 'Are you absolutely sure?',
body: 'This action cannot be undone. This will permanently delete your account and remove your data from our servers.',
actions: [
- FButton(design: FButtonVariant.outline, label: 'Cancel', onPress: () {
+ FButton(style: FButtonStyle.outline, label: 'Cancel', onPress: () {
Navigator.of(context).pop();
}),
FButton(label: 'Continue', onPress: () {}),
diff --git a/forui/lib/forui.dart b/forui/lib/forui.dart
index 156900a97..da438d9be 100644
--- a/forui/lib/forui.dart
+++ b/forui/lib/forui.dart
@@ -17,9 +17,9 @@ export 'src/theme/typography.dart';
export 'src/theme/themes.dart';
// Widgets
-export 'src/widgets/badge/badge.dart' hide FBadgeContent;
+export 'src/widgets/badge/badge.dart' hide FBadgeContent, Variant;
export 'src/foundation/tappable.dart' hide FTappable;
-export 'src/widgets/button/button.dart' hide FButtonContent;
+export 'src/widgets/button/button.dart' hide FButtonContent, Variant;
export 'src/widgets/card/card.dart' hide FCardContent;
export 'src/widgets/dialog/dialog.dart' hide FDialogContent, FHorizontalDialogContent, FVerticalDialogContent;
export 'src/widgets/header/header.dart';
diff --git a/forui/lib/src/theme/color_scheme.dart b/forui/lib/src/theme/color_scheme.dart
index 73a6b6769..9aa920896 100644
--- a/forui/lib/src/theme/color_scheme.dart
+++ b/forui/lib/src/theme/color_scheme.dart
@@ -111,7 +111,7 @@ final class FColorScheme with Diagnosticable {
required this.border,
});
- /// Creates a copy of this [FColorScheme] with the given properties replaced.
+ /// Returns a copy of this [FColorScheme] with the given properties replaced.
///
/// ```dart
/// final scheme = FColorScheme(
diff --git a/forui/lib/src/theme/style.dart b/forui/lib/src/theme/style.dart
index 913c44843..7c12310c8 100644
--- a/forui/lib/src/theme/style.dart
+++ b/forui/lib/src/theme/style.dart
@@ -25,7 +25,7 @@ final class FStyle with Diagnosticable {
this.borderWidth = 1,
});
- /// Creates a copy of this [FStyle] with the given properties replaced.
+ /// Returns a copy of this [FStyle] with the given properties replaced.
///
/// ```dart
/// final style = FStyle(
diff --git a/forui/lib/src/theme/theme.dart b/forui/lib/src/theme/theme.dart
index c0d515b27..1cf36c633 100644
--- a/forui/lib/src/theme/theme.dart
+++ b/forui/lib/src/theme/theme.dart
@@ -75,7 +75,8 @@ class FTheme extends StatelessWidget {
/// );
/// }
/// ```
- @useResult static FThemeData of(BuildContext context) {
+ @useResult
+ static FThemeData of(BuildContext context) {
final theme = context.dependOnInheritedWidgetOfExactType<_InheritedTheme>();
return theme?.data ?? FThemes.zinc.light;
}
@@ -99,25 +100,25 @@ class FTheme extends StatelessWidget {
@override
Widget build(BuildContext context) => _InheritedTheme(
- data: data,
- child: Directionality(
- textDirection: textDirection ?? Directionality.of(context),
- child: DefaultTextStyle(
- style: data.typography.toTextStyle(
- fontSize: data.typography.base,
- color: data.colorScheme.foreground,
+ data: data,
+ child: Directionality(
+ textDirection: textDirection ?? Directionality.of(context),
+ child: DefaultTextStyle(
+ style: data.typography.base.copyWith(
+ fontFamily: data.typography.defaultFontFamily,
+ color: data.colorScheme.foreground,
+ ),
+ child: child,
+ ),
),
- child: child,
- ),
- ),
- );
+ );
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(DiagnosticsProperty('data', data, showName: false))
- ..add(EnumProperty('textDirection', textDirection));
+ ..add(DiagnosticsProperty('data', data, showName: false))
+ ..add(EnumProperty('textDirection', textDirection));
}
}
@@ -132,13 +133,12 @@ class _InheritedTheme extends InheritedWidget {
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
- properties.add(DiagnosticsProperty('data', data));
+ properties.add(DiagnosticsProperty('data', data));
}
}
/// Provides functions for accessing the current [FThemeData].
extension ThemeBuildContext on BuildContext {
-
/// Returns the current [FThemeData], or [FThemes.zinc.light] if there is no ancestor [FTheme].
///
/// ## Troubleshooting:
@@ -180,5 +180,4 @@ extension ThemeBuildContext on BuildContext {
/// }
/// ```
FThemeData get theme => FTheme.of(this);
-
}
diff --git a/forui/lib/src/theme/theme_data.dart b/forui/lib/src/theme/theme_data.dart
index b99170522..32cace336 100644
--- a/forui/lib/src/theme/theme_data.dart
+++ b/forui/lib/src/theme/theme_data.dart
@@ -70,24 +70,33 @@ final class FThemeData with Diagnosticable {
});
/// Creates a [FThemeData] that configures the widget styles using the given properties.
- FThemeData.inherit({
- required this.colorScheme,
- this.typography = const FTypography(),
- this.style = const FStyle(),
- }) : badgeStyles = FBadgeStyles.inherit(colorScheme: colorScheme, typography: typography, style: style),
- buttonStyles = FButtonStyles.inherit(
- colorScheme: colorScheme,
- typography: typography,
- style: style,
- ),
- cardStyle = FCardStyle.inherit(colorScheme: colorScheme, typography: typography, style: style),
- dialogStyle = FDialogStyle.inherit(style: style, colorScheme: colorScheme, typography: typography),
- headerStyle = FHeaderStyle.inherit(colorScheme: colorScheme, typography: typography),
- textFieldStyle = FTextFieldStyle.inherit(colorScheme: colorScheme, typography: typography, style: style),
- separatorStyles = FSeparatorStyles.inherit(colorScheme: colorScheme, style: style),
- switchStyle = FSwitchStyle.inherit(colorScheme: colorScheme);
-
- /// Creates a copy of this [FThemeData] with the given properties replaced.
+ factory FThemeData.inherit({
+ required FColorScheme colorScheme,
+ FStyle style = const FStyle(),
+ FTypography? typography,
+ }) {
+ typography ??= FTypography.inherit(colorScheme: colorScheme);
+
+ return FThemeData(
+ colorScheme: colorScheme,
+ typography: typography,
+ style: style,
+ badgeStyles: FBadgeStyles.inherit(colorScheme: colorScheme, typography: typography, style: style),
+ buttonStyles: FButtonStyles.inherit(
+ colorScheme: colorScheme,
+ typography: typography,
+ style: style,
+ ),
+ cardStyle: FCardStyle.inherit(colorScheme: colorScheme, typography: typography, style: style),
+ dialogStyle: FDialogStyle.inherit(style: style, colorScheme: colorScheme, typography: typography),
+ headerStyle: FHeaderStyle.inherit(colorScheme: colorScheme, typography: typography),
+ textFieldStyle: FTextFieldStyle.inherit(colorScheme: colorScheme, typography: typography, style: style),
+ separatorStyles: FSeparatorStyles.inherit(colorScheme: colorScheme, style: style),
+ switchStyle: FSwitchStyle.inherit(colorScheme: colorScheme),
+ );
+ }
+
+ /// Returns a copy of this [FThemeData] with the given properties replaced.
///
/// ```dart
/// final foo = FTypography();
@@ -103,7 +112,8 @@ final class FThemeData with Diagnosticable {
/// print(theme.colorScheme == copy.colorScheme); // true
/// print(copy.typography); // bar
/// ```
- @useResult FThemeData copyWith({
+ @useResult
+ FThemeData copyWith({
FColorScheme? colorScheme,
FTypography? typography,
FStyle? style,
diff --git a/forui/lib/src/theme/typography.dart b/forui/lib/src/theme/typography.dart
index f315d8806..3fa2e5f39 100644
--- a/forui/lib/src/theme/typography.dart
+++ b/forui/lib/src/theme/typography.dart
@@ -5,9 +5,6 @@ import 'package:meta/meta.dart';
import 'package:forui/forui.dart';
-// TODO: replace with nullable number operations in Sugar 4.
-double? _scale(double? value, double factor) => value == null ? null : value * factor;
-
/// Definitions for the various typographical styles that are part of a [FThemeData].
///
/// A [FTypography] contains scalar values for scaling a [TextStyle]'s corresponding properties. It also contains labelled
@@ -16,217 +13,204 @@ double? _scale(double? value, double factor) => value == null ? null : value * f
/// The scaling is applied automatically in all Forui widgets while the labelled font sizes are used as the defaults
/// for the corresponding properties of widget styles configured via `inherit(...)` constructors.
final class FTypography with Diagnosticable {
-
/// The default font family. Defaults to [`packages/forui/Inter`](https://fonts.google.com/specimen/Inter).
///
/// ## Contract:
/// Throws an [AssertionError] if empty.
final String defaultFontFamily;
- /// A value used to scale [TextStyle.fontSize]. Defaults to 1.
+ /// The font size for extra small text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `sizeScalar` <= 0.0
- /// * `sizeScalar` is NaN
- final double sizeScalar;
+ /// Defaults to:
+ /// * `fontSize` = 12.
+ /// * `height` = 1.
+ final TextStyle xs;
- /// A value used to scale [TextStyle.letterSpacing]. Defaults to 1.
+ /// The font size for small text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `letterSpacingScalar` <= 0.0
- /// * `letterSpacingScalar` is NaN
- final double letterSpacingScalar;
+ /// Defaults to:
+ /// * `fontSize` = 14.
+ /// * `height` = 1.25.
+ final TextStyle sm;
- /// A value used to scale [TextStyle.wordSpacing]. Defaults to 1.
+ /// The font size for base text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `wordSpacingScalar` <= 0.0
- /// * `wordSpacingScalar` is NaN
- final double wordSpacingScalar;
+ /// Defaults to:
+ /// * `fontSize` = 16.
+ /// * `height` = 1.5.
+ final TextStyle base;
- /// A value used to scale [TextStyle.height]. Defaults to 1.
+ /// The font size for large text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `heightScalar` <= 0.0
- /// * `heightScalar` is NaN
- final double heightScalar;
-
- /// The font size for extra small text. Defaults to 12.
- ///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `xs` <= 0.0
- /// * `xs` is NaN
- final double xs;
+ /// Defaults to:
+ /// * `fontSize` = 18.
+ /// * `height` = 1.75.
+ final TextStyle lg;
- /// The font size for small text. Defaults to 14.
+ /// The font size for extra large text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `sm` <= 0.0
- /// * `sm` is NaN
- final double sm;
+ /// Defaults to:
+ /// * `fontSize` = 20.
+ /// * `height` = 1.75.
+ final TextStyle xl;
- /// The font size for base text. Defaults to 16.
+ /// The font size for extra large text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `base` <= 0.0
- /// * `base` is NaN
- final double base;
+ /// Defaults to:
+ /// * `fontSize` = 22.
+ /// * `height` = 2.
+ final TextStyle xl2;
- /// The font size for large text. Defaults to 18.
+ /// The font size for extra large text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `lg` <= 0.0
- /// * `lg` is NaN
- final double lg;
+ /// Defaults to:
+ /// * `fontSize` = 30.
+ /// * `height` = 2.25.
+ final TextStyle xl3;
- /// The font size for extra large text. Defaults to 20.
+ /// The font size for extra large text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `xl` <= 0.0
- /// * `xl` is NaN
- final double xl;
+ /// Defaults to:
+ /// * `fontSize` = 36.
+ /// * `height` = 2.5.
+ final TextStyle xl4;
- /// The font size for extra large text. Defaults to 22.
+ /// The font size for extra large text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `xl2` <= 0.0
- /// * `xl2` is NaN
- final double xl2;
+ /// Defaults to:
+ /// * `fontSize` = 48.
+ /// * `height` = 1.
+ final TextStyle xl5;
- /// The font size for extra large text. Defaults to 30.
+ /// The font size for extra large text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `xl3` <= 0.0
- /// * `xl3` is NaN
- final double xl3;
+ /// Defaults to:
+ /// * `fontSize` = 60.
+ /// * `height` = 1.
+ final TextStyle xl6;
- /// The font size for extra large text. Defaults to 36.
+ /// The font size for extra large text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `xl4` <= 0.0
- /// * `xl4` is NaN
- final double xl4;
+ /// Defaults to:
+ /// * `fontSize` = 72.
+ /// * `height` = 1.
+ final TextStyle xl7;
- /// The font size for extra large text. Defaults to 48.
+ /// The font size for extra large text.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `xl5` <= 0.0
- /// * `xl5` is NaN
- final double xl5;
+ /// Defaults to:
+ /// * `fontSize` = 96.
+ /// * `height` = 1.
+ final TextStyle xl8;
- /// The font size for extra large text. Defaults to 60.
- ///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `xl6` <= 0.0
- /// * `xl6` is NaN
- final double xl6;
+ /// Creates a [FTypography].
+ const FTypography({
+ this.defaultFontFamily = 'packages/forui/Inter',
+ this.xs = const TextStyle(fontSize: 12, height: 1),
+ this.sm = const TextStyle(fontSize: 14, height: 1.25),
+ this.base = const TextStyle(fontSize: 16, height: 1.5),
+ this.lg = const TextStyle(fontSize: 18, height: 1.75),
+ this.xl = const TextStyle(fontSize: 20, height: 1.75),
+ this.xl2 = const TextStyle(fontSize: 22, height: 2),
+ this.xl3 = const TextStyle(fontSize: 30, height: 2.25),
+ this.xl4 = const TextStyle(fontSize: 36, height: 2.5),
+ this.xl5 = const TextStyle(fontSize: 48, height: 1),
+ this.xl6 = const TextStyle(fontSize: 60, height: 1),
+ this.xl7 = const TextStyle(fontSize: 72, height: 1),
+ this.xl8 = const TextStyle(fontSize: 96, height: 1),
+ }) : assert(0 < defaultFontFamily.length, 'The defaultFontFamily should not be empty.');
- /// The font size for extra large text. Defaults to 72.
- ///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `xl7` <= 0.0
- /// * `xl7` is NaN
- final double xl7;
+ /// Creates a [FTypography] that inherits its properties from [colorScheme].
+ FTypography.inherit({
+ required FColorScheme colorScheme,
+ this.defaultFontFamily = 'packages/forui/Inter',
+ }) : xs = TextStyle(color: colorScheme.foreground, fontSize: 12, height: 1),
+ sm = TextStyle(color: colorScheme.foreground, fontSize: 14, height: 1.25),
+ base = TextStyle(color: colorScheme.foreground, fontSize: 16, height: 1.5),
+ lg = TextStyle(color: colorScheme.foreground, fontSize: 18, height: 1.75),
+ xl = TextStyle(color: colorScheme.foreground, fontSize: 20, height: 1.75),
+ xl2 = TextStyle(color: colorScheme.foreground, fontSize: 22, height: 2),
+ xl3 = TextStyle(color: colorScheme.foreground, fontSize: 30, height: 2.25),
+ xl4 = TextStyle(color: colorScheme.foreground, fontSize: 36, height: 2.5),
+ xl5 = TextStyle(color: colorScheme.foreground, fontSize: 48, height: 1),
+ xl6 = TextStyle(color: colorScheme.foreground, fontSize: 60, height: 1),
+ xl7 = TextStyle(color: colorScheme.foreground, fontSize: 72, height: 1),
+ xl8 = TextStyle(color: colorScheme.foreground, fontSize: 96, height: 1),
+ assert(defaultFontFamily.isNotEmpty, 'The defaultFontFamily should not be empty.');
- /// The font size for extra large text. Defaults to 96.
+ /// Scales the fields of this [FTypography] by the given fields.
///
- /// ## Contract:
- /// Throws an [AssertionError] if:
- /// * `xl8` <= 0.0
- /// * `xl8` is NaN
- final double xl8;
+ /// ```dart
+ /// const typography = FTypography(
+ /// sm: TextStyle(fontSize: 10),
+ /// base: TextStyle(fontSize: 20),
+ /// );
+ ///
+ /// final scaled = typography.scale(sizeScalar: 1.5);
+ ///
+ /// print(scaled.sm.fontSize); // 15
+ /// print(scaled.base.fontSize); // 30
+ /// ```
+ @useResult
+ FTypography scale({double sizeScalar = 1}) => FTypography(
+ defaultFontFamily: defaultFontFamily,
+ xs: _scaleTextStyle(style: xs, sizeScalar: sizeScalar),
+ sm: _scaleTextStyle(style: sm, sizeScalar: sizeScalar),
+ base: _scaleTextStyle(style: base, sizeScalar: sizeScalar),
+ lg: _scaleTextStyle(style: lg, sizeScalar: sizeScalar),
+ xl: _scaleTextStyle(style: xl, sizeScalar: sizeScalar),
+ xl2: _scaleTextStyle(style: xl2, sizeScalar: sizeScalar),
+ xl3: _scaleTextStyle(style: xl3, sizeScalar: sizeScalar),
+ xl4: _scaleTextStyle(style: xl4, sizeScalar: sizeScalar),
+ xl5: _scaleTextStyle(style: xl5, sizeScalar: sizeScalar),
+ xl6: _scaleTextStyle(style: xl6, sizeScalar: sizeScalar),
+ xl7: _scaleTextStyle(style: xl7, sizeScalar: sizeScalar),
+ xl8: _scaleTextStyle(style: xl8, sizeScalar: sizeScalar),
+ );
- /// Creates a [FTypography].
- const FTypography({
- this.defaultFontFamily = 'packages/forui/Inter',
- this.sizeScalar = 1,
- this.letterSpacingScalar = 1,
- this.wordSpacingScalar = 1,
- this.heightScalar = 1,
- this.xs = 12,
- this.sm = 14,
- this.base = 16,
- this.lg = 18,
- this.xl = 20,
- this.xl2 = 22,
- this.xl3 = 30,
- this.xl4 = 36,
- this.xl5 = 48,
- this.xl6 = 60,
- this.xl7 = 72,
- this.xl8 = 96,
- }):
- assert(0 < defaultFontFamily.length, 'The defaultFontFamily should not be empty.'),
- assert(0 < sizeScalar, 'The sizeScalar is $sizeScalar, but it should be in the range "0 < sizeScalar".'),
- assert(0 < letterSpacingScalar, 'The letterSpacingScalar is $letterSpacingScalar, but it should be in the range "0 < letterSpacingScalar".'),
- assert(0 < wordSpacingScalar, 'The wordSpacingScalar is $wordSpacingScalar, but it should be in the range "0 < wordSpacingScalar".'),
- assert(0 < heightScalar, 'The heightScalar is $heightScalar, but it should be in the range "0 < heightScalar".'),
- assert(0 < xs, 'The xs is $xs, but it should be in the range "0 < xs".'),
- assert(0 < sm, 'The sm is $sm, but it should be in the range "0 < sm".'),
- assert(0 < base, 'The base is $base, but it should be in the range "0 < base".'),
- assert(0 < lg, 'The lg is $lg, but it should be in the range "0 < lg".'),
- assert(0 < xl, 'The xl is $xl, but it should be in the range "0 < xl".'),
- assert(0 < xl2, 'The xl2 is $xl2, but it should be in the range "0 < xl2".'),
- assert(0 < xl3, 'The xl3 is $xl3, but it should be in the range "0 < xl3".'),
- assert(0 < xl4, 'The xl4 is $xl4, but it should be in the range "0 < xl4".'),
- assert(0 < xl5, 'The xl5 is $xl5, but it should be in the range "0 < xl5".'),
- assert(0 < xl6, 'The xl6 is $xl6, but it should be in the range "0 < xl6".'),
- assert(0 < xl7, 'The xl7 is $xl7, but it should be in the range "0 < xl7".'),
- assert(0 < xl8, 'The xl8 is $xl8, but it should be in the range "0 < xl8".');
+ TextStyle _scaleTextStyle({
+ required TextStyle style,
+ required double sizeScalar,
+ }) {
+ // default font size; https://api.flutter.dev/flutter/painting/TextStyle/fontSize.html
+ final double fontSize = style.fontSize ?? 14;
+
+ return style.copyWith(fontSize: fontSize * sizeScalar);
+ }
- /// Creates a copy of this [FTypography] with the given properties replaced.
+ /// Returns a copy of this [FTypography] with the given properties replaced.
///
/// ```dart
/// const typography = FTypography(
/// defaultFontFamily: 'packages/forui/my-font',
- /// sizeScalar: 2,
+ /// sm: TextStyle(fontSize: 10),
+ /// base: TextStyle(fontSize: 20),
/// );
///
- /// final copy = typography.copyWith(sizeScalar: 3);
+ /// final copy = typography.copyWith(defaultFontFamily: 'packages/forui/another-font');
///
- /// print(copy.defaultFontFamily); // 'packages/forui/my-font'
- /// print(copy.sizeScalar); // 3
+ /// print(copy.defaultFontFamily); // 'packages/forui/another-font'
+ /// print(copy.sm.fontSize); // 10
+ /// print(copy.base.fontSize); // 20
/// ```
- @useResult FTypography copyWith({
+ @useResult
+ FTypography copyWith({
String? defaultFontFamily,
- double? sizeScalar,
- double? letterSpacingScalar,
- double? wordSpacingScalar,
- double? heightScalar,
- double? xs,
- double? sm,
- double? base,
- double? lg,
- double? xl,
- double? xl2,
- double? xl3,
- double? xl4,
- double? xl5,
- double? xl6,
- double? xl7,
- double? xl8,
+ TextStyle? xs,
+ TextStyle? sm,
+ TextStyle? base,
+ TextStyle? lg,
+ TextStyle? xl,
+ TextStyle? xl2,
+ TextStyle? xl3,
+ TextStyle? xl4,
+ TextStyle? xl5,
+ TextStyle? xl6,
+ TextStyle? xl7,
+ TextStyle? xl8,
}) =>
FTypography(
defaultFontFamily: defaultFontFamily ?? this.defaultFontFamily,
- sizeScalar: sizeScalar ?? this.sizeScalar,
- letterSpacingScalar: letterSpacingScalar ?? this.letterSpacingScalar,
- wordSpacingScalar: wordSpacingScalar ?? this.wordSpacingScalar,
- heightScalar: heightScalar ?? this.heightScalar,
xs: xs ?? this.xs,
sm: sm ?? this.sm,
base: base ?? this.base,
@@ -241,134 +225,47 @@ final class FTypography with Diagnosticable {
xl8: xl8 ?? this.xl8,
);
- /// Returns a [TextStyle] with the given properties, based on, and scaled using this [FTypography].
- ///
- /// ```dart
- /// final typography = FTypography(
- /// defaultFontFamily: 'packages/forui/my-font',
- /// sizeScalar: 2,
- /// letterSpacingScalar: 3,
- /// wordSpacingScalar: 4,
- /// heightScalar: 5,
- /// );
- ///
- /// final style = typography.toTextStyle(
- /// fontSize: 1,
- /// letterSpacing: 1,
- /// wordSpacing: 1,
- /// height: 1,
- /// );
- ///
- /// print(style.fontFamily); // 'packages/forui/my-font'
- /// print(style.fontSize); // 2
- /// print(style.letterSpacing); // 3
- /// print(style.wordSpacing); // 4
- /// print(style.height); // 5
- /// ```
- @useResult TextStyle toTextStyle({
- bool inherit = true,
- Color? color,
- Color? backgroundColor,
- double? fontSize,
- FontWeight? fontWeight,
- FontStyle? fontStyle,
- double? letterSpacing,
- double? wordSpacing,
- TextBaseline? textBaseline,
- double? height,
- TextLeadingDistribution? leadingDistribution,
- Locale? locale,
- Paint? foreground,
- Paint? background,
- List? shadows,
- List? fontFeatures,
- List? fontVariations,
- TextDecoration? decoration,
- Color? decorationColor,
- TextDecorationStyle? decorationStyle,
- double? decorationThickness,
- String? debugLabel,
- TextOverflow? overflow,
- }) => TextStyle(
- inherit: inherit,
- color: color,
- backgroundColor: backgroundColor,
- fontSize: _scale(fontSize, sizeScalar),
- fontWeight: fontWeight,
- fontStyle: fontStyle,
- letterSpacing: _scale(letterSpacing, letterSpacingScalar),
- wordSpacing: _scale(wordSpacing, wordSpacingScalar),
- textBaseline: textBaseline,
- height: _scale(height, heightScalar),
- leadingDistribution: leadingDistribution,
- locale: locale,
- foreground: foreground,
- background: background,
- shadows: shadows,
- fontFeatures: fontFeatures,
- fontVariations: fontVariations,
- decoration: decoration,
- decorationColor: decorationColor,
- decorationStyle: decorationStyle,
- decorationThickness: decorationThickness,
- debugLabel: debugLabel,
- fontFamily: defaultFontFamily,
- overflow: overflow,
- );
-
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(StringProperty('family', defaultFontFamily, defaultValue: 'packages/forui/Inter'))
- ..add(DoubleProperty('sizeScalar', sizeScalar, defaultValue: 1))
- ..add(DoubleProperty('letterSpacingScalar', letterSpacingScalar, defaultValue: 1))
- ..add(DoubleProperty('wordSpacingScalar', wordSpacingScalar, defaultValue: 1))
- ..add(DoubleProperty('heightScalar', heightScalar, defaultValue: 1))
- ..add(DoubleProperty('xs', xs, defaultValue: 12))
- ..add(DoubleProperty('sm', sm, defaultValue: 14))
- ..add(DoubleProperty('base', base, defaultValue: 16))
- ..add(DoubleProperty('lg', lg, defaultValue: 18))
- ..add(DoubleProperty('xl', xl, defaultValue: 20))
- ..add(DoubleProperty('xl2', xl2, defaultValue: 22))
- ..add(DoubleProperty('xl3', xl3, defaultValue: 30))
- ..add(DoubleProperty('xl4', xl4, defaultValue: 36))
- ..add(DoubleProperty('xl5', xl5, defaultValue: 48))
- ..add(DoubleProperty('xl6', xl6, defaultValue: 60))
- ..add(DoubleProperty('xl7', xl7, defaultValue: 72))
- ..add(DoubleProperty('xl8', xl8, defaultValue: 96));
+ ..add(DiagnosticsProperty('xs', xs, defaultValue: 12))
+ ..add(DiagnosticsProperty('sm', sm, defaultValue: 14))
+ ..add(DiagnosticsProperty('base', base, defaultValue: 16))
+ ..add(DiagnosticsProperty('lg', lg, defaultValue: 18))
+ ..add(DiagnosticsProperty('xl', xl, defaultValue: 20))
+ ..add(DiagnosticsProperty('xl2', xl2, defaultValue: 22))
+ ..add(DiagnosticsProperty('xl3', xl3, defaultValue: 30))
+ ..add(DiagnosticsProperty('xl4', xl4, defaultValue: 36))
+ ..add(DiagnosticsProperty('xl5', xl5, defaultValue: 48))
+ ..add(DiagnosticsProperty('xl6', xl6, defaultValue: 60))
+ ..add(DiagnosticsProperty('xl7', xl7, defaultValue: 72))
+ ..add(DiagnosticsProperty('xl8', xl8, defaultValue: 96));
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
- other is FTypography &&
- runtimeType == other.runtimeType &&
- defaultFontFamily == other.defaultFontFamily &&
- sizeScalar == other.sizeScalar &&
- letterSpacingScalar == other.letterSpacingScalar &&
- wordSpacingScalar == other.wordSpacingScalar &&
- heightScalar == other.heightScalar &&
- xs == other.xs &&
- sm == other.sm &&
- base == other.base &&
- lg == other.lg &&
- xl == other.xl &&
- xl2 == other.xl2 &&
- xl3 == other.xl3 &&
- xl4 == other.xl4 &&
- xl5 == other.xl5 &&
- xl6 == other.xl6 &&
- xl7 == other.xl7 &&
- xl8 == other.xl8;
+ other is FTypography &&
+ runtimeType == other.runtimeType &&
+ defaultFontFamily == other.defaultFontFamily &&
+ xs == other.xs &&
+ sm == other.sm &&
+ base == other.base &&
+ lg == other.lg &&
+ xl == other.xl &&
+ xl2 == other.xl2 &&
+ xl3 == other.xl3 &&
+ xl4 == other.xl4 &&
+ xl5 == other.xl5 &&
+ xl6 == other.xl6 &&
+ xl7 == other.xl7 &&
+ xl8 == other.xl8;
@override
int get hashCode =>
defaultFontFamily.hashCode ^
- sizeScalar.hashCode ^
- letterSpacingScalar.hashCode ^
- wordSpacingScalar.hashCode ^
- heightScalar.hashCode ^
xs.hashCode ^
sm.hashCode ^
base.hashCode ^
@@ -382,40 +279,3 @@ final class FTypography with Diagnosticable {
xl7.hashCode ^
xl8.hashCode;
}
-
-/// Provides functions for working with [FTypography]s.
-extension TypographyTextStyle on TextStyle {
-
- /// Scales a [TextStyle] using the given [typography].
- ///
- /// ```dart
- /// final typography = FTypography(
- /// defaultFontFamily: 'packages/forui/my-font',
- /// sizeScalar: 2,
- /// letterSpacingScalar: 3,
- /// wordSpacingScalar: 4,
- /// heightScalar: 5,
- /// );
- ///
- /// final style = TextStyle(
- /// fontFamily: 'default-font',
- /// fontSize: 1,
- /// letterSpacing: 1,
- /// wordSpacing: 1,
- /// height: 1,
- /// ).scale(typography);
- ///
- /// print(style.fontFamily); // 'default-font'
- /// print(style.fontSize); // 2
- /// print(style.letterSpacing); // 3
- /// print(style.wordSpacing); // 4
- /// print(style.height); // 5
- /// ```
- @useResult TextStyle scale(FTypography typography) => copyWith(
- fontSize: _scale(fontSize, typography.sizeScalar),
- letterSpacing: _scale(letterSpacing, typography.letterSpacingScalar),
- wordSpacing: _scale(wordSpacing, typography.wordSpacingScalar),
- height: _scale(height, typography.heightScalar),
- );
-
-}
diff --git a/forui/lib/src/widgets/badge/badge.dart b/forui/lib/src/widgets/badge/badge.dart
index da4eb8ea8..565bc34c8 100644
--- a/forui/lib/src/widgets/badge/badge.dart
+++ b/forui/lib/src/widgets/badge/badge.dart
@@ -8,35 +8,52 @@ import 'package:forui/forui.dart';
part 'badge_content.dart';
part 'badge_styles.dart';
-/// A badge, or a component that looks like a badge.
+/// A badge. Badges are typically used to draw attention to specific information, such as labels and counts.
+///
+/// The constants in [FBadgeStyle] provide a convenient way to style a badge.
+///
+/// See:
+/// * https://forui.dev/docs/badge for working examples.
+/// * [FBadgeCustomStyle] for customizing a badge's appearance.
class FBadge extends StatelessWidget {
- /// The design. Defaults to [FBadgeVariant.primary].
- final FBadgeDesign design;
+ /// The style. Defaults to [FBadgeStyle.primary].
+ ///
+ /// Although typically one of the pre-defined styles in [FBadgeStyle], it can also be a [FBadgeCustomStyle].
+ final FBadgeStyle style;
- /// The builder.
- final Widget Function(BuildContext, FBadgeStyle) builder;
+ /// The builder used to build the badge's content.
+ final Widget Function(BuildContext, FBadgeCustomStyle) builder;
- /// Creates a [FBadge].
+ /// Creates a [FBadge] that contains a [label] or a [rawLabel].
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * both [label] and [rawLabel] are not null
+ /// * both [label] and [rawLabel] are null
FBadge({
String? label,
Widget? rawLabel,
- this.design = FBadgeVariant.primary,
+ this.style = FBadgeStyle.primary,
super.key,
}) :
assert((label == null) ^ (rawLabel == null), 'Either "label" or "rawLabel" must be provided, but not both.'),
builder = ((context, style) => FBadgeContent(rawLabel: rawLabel, label: label, style: style));
- /// Creates a [FBadge].
- const FBadge.raw({required this.design, required this.builder, super.key});
+ /// Creates a [FBadge] with custom content.
+ const FBadge.raw({
+ required this.builder,
+ this.style = FBadgeStyle.primary,
+ super.key,
+ });
@override
Widget build(BuildContext context) {
- final style = switch (design) {
- final FBadgeStyle style => style,
- FBadgeVariant.primary => context.theme.badgeStyles.primary,
- FBadgeVariant.secondary => context.theme.badgeStyles.secondary,
- FBadgeVariant.outline => context.theme.badgeStyles.outline,
- FBadgeVariant.destructive => context.theme.badgeStyles.destructive,
+ final style = switch (this.style) {
+ final FBadgeCustomStyle style => style,
+ FBadgeStyle.primary => context.theme.badgeStyles.primary,
+ FBadgeStyle.secondary => context.theme.badgeStyles.secondary,
+ FBadgeStyle.outline => context.theme.badgeStyles.outline,
+ FBadgeStyle.destructive => context.theme.badgeStyles.destructive,
};
return IntrinsicWidth(
@@ -44,11 +61,11 @@ class FBadge extends StatelessWidget {
child: DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
- color: style.border,
+ color: style.borderColor,
width: style.borderWidth,
),
borderRadius: style.borderRadius,
- color: style.background,
+ color: style.backgroundColor,
),
child: builder(context, style),
),
@@ -60,81 +77,111 @@ class FBadge extends StatelessWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(DiagnosticsProperty('design', design, defaultValue: FBadgeVariant.primary))
- ..add(DiagnosticsProperty('builder', builder, defaultValue: null));
+ ..add(DiagnosticsProperty('style', style, defaultValue: FBadgeStyle.primary))
+ ..add(DiagnosticsProperty('builder', builder, level: DiagnosticLevel.debug));
}
}
-/// The badge design. Either a pre-defined [FBadgeVariant], or a custom [FBadgeStyle].
-sealed class FBadgeDesign {}
-/// A pre-defined badge variant.
-enum FBadgeVariant implements FBadgeDesign {
- /// A primary-styled badge.
- primary,
+/// A [FBadge]'s style.
+///
+/// A style can be either one of the pre-defined styles in [FBadgeStyle] or a [FBadgeCustomStyle]. The pre-defined styles
+/// are a convenient shorthand for the various [FBadgeCustomStyle]s in the current context's [FBadgeStyles].
+sealed class FBadgeStyle {
+ /// The badge's primary style.
+ ///
+ /// Shorthand for the current context's [FBadgeStyles.primary] style.
+ static const FBadgeStyle primary = Variant.primary;
- /// A secondary-styled badge.
- secondary,
+ /// The badge's secondary style.
+ ///
+ /// Shorthand for the current context's [FBadgeStyles.secondary] style.
+ static const FBadgeStyle secondary = Variant.secondary;
- /// An outlined badge.
- outline,
+ /// The badge's outline style.
+ ///
+ /// Shorthand for the current context's [FBadgeStyles.outline] style.
+ static const FBadgeStyle outline = Variant.outline;
- /// A destructive badge.
- destructive,
+ /// The badge's destructive style.
+ ///
+ /// Shorthand for the current context's [FBadgeStyles.destructive] style.
+ static const FBadgeStyle destructive = Variant.destructive;
}
-/// A [FBadge]'s style.
-final class FBadgeStyle with Diagnosticable implements FBadgeDesign {
+@internal enum Variant implements FBadgeStyle {
+ primary,
+ secondary,
+ outline,
+ destructive,
+}
+/// A custom [FBadge] style.
+final class FBadgeCustomStyle with Diagnosticable implements FBadgeStyle {
/// The background color.
- final Color background;
+ final Color backgroundColor;
/// The border color.
- final Color border;
+ final Color borderColor;
- /// The border radius.
+ /// The border radius. Defaults to `BorderRadius.circular(100)`.
final BorderRadius borderRadius;
- /// The border width (thickness). Defaults to 1.
+ /// The border width (thickness).
///
/// ## Contract:
- /// Throws an [AssertionError] if:
+ /// Throws [AssertionError] if:
/// * `borderWidth` <= 0.0
/// * `borderWidth` is Nan
final double borderWidth;
- /// The button content's style.
+ /// The badge content's style.
final FBadgeContentStyle content;
- /// Creates a [FBadgeStyle].
- FBadgeStyle({
- required this.background,
- required this.border,
- required this.borderRadius,
+ /// Creates a [FBadgeCustomStyle].
+ FBadgeCustomStyle({
+ required this.backgroundColor,
+ required this.borderColor,
required this.content,
+ this.borderRadius = const BorderRadius.all(Radius.circular(100)),
this.borderWidth = 1,
}) : assert(0 < borderWidth, 'The borderWidth is $borderWidth, but it should be in the range "0 < borderWidth".');
- /// Creates a [FBadgeStyle] that inherits its properties from [style].
- FBadgeStyle.inherit({
+ /// Creates a [FBadgeCustomStyle] that inherits its properties from [style].
+ FBadgeCustomStyle.inherit({
required FStyle style,
- required this.background,
- required this.border,
+ required this.backgroundColor,
+ required this.borderColor,
required this.content,
}) : borderRadius = BorderRadius.circular(100),
borderWidth = style.borderWidth;
- /// Creates a copy of this [FBadgeStyle] with the given properties replaced.
- FBadgeStyle copyWith({
- Color? background,
- Color? border,
+ /// Returns a copy of this [FBadgeCustomStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FBadgeCustomStyle(
+ /// backgroundColor: Colors.red,
+ /// borderColor: Colors.black,
+ /// // other properties omitted for brevity
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// backgroundColor: Colors.blue,
+ /// );
+ ///
+ /// print(copy.backgroundColor); // Colors.blue
+ /// print(copy.borderColor); // Colors.black
+ /// ```
+ @useResult FBadgeCustomStyle copyWith({
+ Color? backgroundColor,
+ Color? borderColor,
BorderRadius? borderRadius,
double? borderWidth,
FBadgeContentStyle? content,
}) =>
- FBadgeStyle(
- background: background ?? this.background,
- border: border ?? this.border,
+ FBadgeCustomStyle(
+ backgroundColor: backgroundColor ?? this.backgroundColor,
+ borderColor: borderColor ?? this.borderColor,
borderRadius: borderRadius ?? this.borderRadius,
borderWidth: borderWidth ?? this.borderWidth,
content: content ?? this.content,
@@ -144,8 +191,8 @@ final class FBadgeStyle with Diagnosticable implements FBadgeDesign {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(ColorProperty('background', background))
- ..add(ColorProperty('border', border))
+ ..add(ColorProperty('backgroundColor', backgroundColor))
+ ..add(ColorProperty('borderColor', borderColor))
..add(DiagnosticsProperty('borderRadius', borderRadius, defaultValue: BorderRadius.circular(100)))
..add(DoubleProperty('borderWidth', borderWidth))
..add(DiagnosticsProperty('content', content));
@@ -154,15 +201,15 @@ final class FBadgeStyle with Diagnosticable implements FBadgeDesign {
@override
bool operator ==(Object other) =>
identical(this, other) ||
- other is FBadgeStyle &&
+ other is FBadgeCustomStyle &&
runtimeType == other.runtimeType &&
- background == other.background &&
- border == other.border &&
+ backgroundColor == other.backgroundColor &&
+ borderColor == other.borderColor &&
borderRadius == other.borderRadius &&
borderWidth == other.borderWidth &&
content == other.content;
@override
int get hashCode =>
- background.hashCode ^ border.hashCode ^ borderRadius.hashCode ^ borderWidth.hashCode ^ content.hashCode;
+ backgroundColor.hashCode ^ borderColor.hashCode ^ borderRadius.hashCode ^ borderWidth.hashCode ^ content.hashCode;
}
diff --git a/forui/lib/src/widgets/badge/badge_content.dart b/forui/lib/src/widgets/badge/badge_content.dart
index 3e7b6b01c..5a63720fb 100644
--- a/forui/lib/src/widgets/badge/badge_content.dart
+++ b/forui/lib/src/widgets/badge/badge_content.dart
@@ -1,7 +1,8 @@
part of 'badge.dart';
-@internal final class FBadgeContent extends StatelessWidget {
- final FBadgeStyle style;
+@internal
+final class FBadgeContent extends StatelessWidget {
+ final FBadgeCustomStyle style;
final String? label;
final Widget? rawLabel;
@@ -17,7 +18,7 @@ part of 'badge.dart';
child: Padding(
padding: style.content.padding,
child: DefaultTextStyle.merge(
- style: style.content.label.scale(context.theme.typography),
+ style: style.content.labelTextStyle,
child: switch ((label, rawLabel)) {
(final String label, _) => Text(label),
(_, final Widget label) => label,
@@ -32,24 +33,39 @@ part of 'badge.dart';
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty('style', style))
- ..add(StringProperty('labelText', label));
+ ..add(StringProperty('label', label));
}
}
/// A badge content's style.
final class FBadgeContentStyle with Diagnosticable {
- /// The text.
- final TextStyle label;
+ /// The label's [TextStyle].
+ final TextStyle labelTextStyle;
- /// The padding.
+ /// The padding. Defaults to `EdgeInsets.symmetric(horizontal: 14, vertical: 2)`.
final EdgeInsets padding;
/// Creates a [FBadgeContentStyle].
- FBadgeContentStyle({required this.label, this.padding = const EdgeInsets.symmetric(horizontal: 14, vertical: 2)});
+ FBadgeContentStyle({
+ required this.labelTextStyle,
+ this.padding = const EdgeInsets.symmetric(horizontal: 14, vertical: 2),
+ });
- /// Creates a copy of this [FBadgeContentStyle] with the given properties replaced.
- FBadgeContentStyle copyWith({TextStyle? label, EdgeInsets? padding}) => FBadgeContentStyle(
- label: label ?? this.label,
+ /// Returns a copy of this [FBadgeContentStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FBadgeContentStyle(
+ /// labelTextStyle: TextStyle(...),
+ /// padding = EdgeInsets.zero,
+ /// );
+ ///
+ /// final copy = style.copyWith(padding: EdgeInsets.symmetric(vertical: 10));
+ ///
+ /// print(style.labelTextStyle == copy.labelTextStyle); // true
+ /// print(style.padding == copy.padding); // false
+ /// ```
+ @useResult FBadgeContentStyle copyWith({TextStyle? labelTextStyle, EdgeInsets? padding}) => FBadgeContentStyle(
+ labelTextStyle: labelTextStyle ?? this.labelTextStyle,
padding: padding ?? this.padding,
);
@@ -57,15 +73,15 @@ final class FBadgeContentStyle with Diagnosticable {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(DiagnosticsProperty('label', label))
+ ..add(DiagnosticsProperty('labelTextStyle', labelTextStyle))
..add(DiagnosticsProperty('padding', padding, defaultValue: const EdgeInsets.symmetric(horizontal: 14, vertical: 2)));
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
- other is FBadgeContentStyle && runtimeType == other.runtimeType && padding == other.padding && label == other.label;
+ other is FBadgeContentStyle && runtimeType == other.runtimeType && padding == other.padding && labelTextStyle == other.labelTextStyle;
@override
- int get hashCode => padding.hashCode ^ label.hashCode;
+ int get hashCode => padding.hashCode ^ labelTextStyle.hashCode;
}
diff --git a/forui/lib/src/widgets/badge/badge_styles.dart b/forui/lib/src/widgets/badge/badge_styles.dart
index 4a9469960..b5fd46bc3 100644
--- a/forui/lib/src/widgets/badge/badge_styles.dart
+++ b/forui/lib/src/widgets/badge/badge_styles.dart
@@ -1,79 +1,92 @@
part of 'badge.dart';
-/// The [FBadgeStyle]s.
+/// The [FBadgeCustomStyle]s.
class FBadgeStyles with Diagnosticable {
/// The primary badge style.
- final FBadgeStyle primary;
+ final FBadgeCustomStyle primary;
/// The secondary badge style.
- final FBadgeStyle secondary;
+ final FBadgeCustomStyle secondary;
/// The outlined badge style.
- final FBadgeStyle outline;
+ final FBadgeCustomStyle outline;
/// The destructive badge style.
- final FBadgeStyle destructive;
+ final FBadgeCustomStyle destructive;
/// Creates a [FBadgeStyles].
- FBadgeStyles({required this.primary, required this.secondary, required this.outline, required this.destructive});
+ FBadgeStyles({
+ required this.primary,
+ required this.secondary,
+ required this.outline,
+ required this.destructive,
+ });
- /// Creates a [FBadgeStyles] that inherits its properties from [colorScheme] and [style].
+ /// Creates a [FBadgeStyles] that inherits its properties from the provided [colorScheme], [typography], and [style].
FBadgeStyles.inherit({required FColorScheme colorScheme, required FTypography typography, required FStyle style}):
- primary = FBadgeStyle.inherit(
+ primary = FBadgeCustomStyle.inherit(
style: style,
- background: colorScheme.primary,
- border: colorScheme.primary,
+ backgroundColor: colorScheme.primary,
+ borderColor: colorScheme.primary,
content: FBadgeContentStyle(
- label: TextStyle(
+ labelTextStyle: typography.sm.copyWith(
color: colorScheme.primaryForeground,
- fontSize: typography.sm,
fontWeight: FontWeight.w600,
),
),
),
- secondary = FBadgeStyle.inherit(
+ secondary = FBadgeCustomStyle.inherit(
style: style,
- background: colorScheme.secondary,
- border: colorScheme.secondary,
+ backgroundColor: colorScheme.secondary,
+ borderColor: colorScheme.secondary,
content: FBadgeContentStyle(
- label: TextStyle(
+ labelTextStyle: typography.sm.copyWith(
color: colorScheme.secondaryForeground,
- fontSize: typography.sm,
fontWeight: FontWeight.w600,
),
),
),
- outline = FBadgeStyle.inherit(
+ outline = FBadgeCustomStyle.inherit(
style: style,
- background: colorScheme.background,
- border: colorScheme.border,
+ backgroundColor: colorScheme.background,
+ borderColor: colorScheme.border,
content: FBadgeContentStyle(
- label: TextStyle(
+ labelTextStyle: typography.sm.copyWith(
color: colorScheme.foreground,
- fontSize: typography.sm,
fontWeight: FontWeight.w600,
),
),
),
- destructive = FBadgeStyle.inherit(
+ destructive = FBadgeCustomStyle.inherit(
style: style,
- background: colorScheme.destructive,
- border: colorScheme.destructive,
+ backgroundColor: colorScheme.destructive,
+ borderColor: colorScheme.destructive,
content: FBadgeContentStyle(
- label: TextStyle(
+ labelTextStyle: typography.sm.copyWith(
color: colorScheme.destructiveForeground,
- fontSize: typography.sm,
fontWeight: FontWeight.w600,
),
),
);
- /// Creates a copy of this [FBadgeStyles] with the given properties replaced.
- FBadgeStyles copyWith({
- FBadgeStyle? primary,
- FBadgeStyle? secondary,
- FBadgeStyle? outline,
- FBadgeStyle? destructive,
+ /// Returns a copy of this [FBadgeStyles] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final styles = FBadgeStyles(
+ /// primary: ...,
+ /// secondary: ...,
+ /// );
+ ///
+ /// final copy = styles.copyWith(secondary: ...);
+ ///
+ /// print(styles.primary == copy.primary); // true
+ /// print(styles.secondary == copy.secondary); // false
+ /// ```
+ @useResult FBadgeStyles copyWith({
+ FBadgeCustomStyle? primary,
+ FBadgeCustomStyle? secondary,
+ FBadgeCustomStyle? outline,
+ FBadgeCustomStyle? destructive,
}) => FBadgeStyles(
primary: primary ?? this.primary,
secondary: secondary ?? this.secondary,
diff --git a/forui/lib/src/widgets/button/button.dart b/forui/lib/src/widgets/button/button.dart
index e50d23c18..bbea3c6eb 100644
--- a/forui/lib/src/widgets/button/button.dart
+++ b/forui/lib/src/widgets/button/button.dart
@@ -14,6 +14,15 @@ part 'button_icon.dart';
part 'button_styles.dart';
/// A button.
+///
+/// [FButton]s typically contain icons and/or a label. If the [onPress] and [onLongPress] callbacks are null, then this
+/// button will be disabled, it will not react to touch.
+///
+/// The constants in [FButtonStyle] provide a convenient way to style a badge.
+///
+/// See:
+/// * https://forui.dev/docs/button for working examples.
+/// * [FButtonCustomStyle] for customizing a button's appearance.
class FButton extends StatelessWidget {
@useResult
static _Data _of(BuildContext context) {
@@ -21,21 +30,27 @@ class FButton extends StatelessWidget {
return theme?.data ?? (style: context.theme.buttonStyles.primary, enabled: true);
}
- /// The design. Defaults to [FBadgeVariant.primary].
- final FButtonDesign design;
+ /// The style. Defaults to [FButtonStyle.primary].
+ ///
+ /// Although typically one of the pre-defined styles in [FButtonStyle], it can also be a [FButtonCustomStyle].
+ final FButtonStyle style;
/// A callback for when the button is pressed.
+ ///
+ /// The button will be disabled if both [onPress] and [onLongPress] are null.
final VoidCallback? onPress;
/// A callback for when the button is long pressed.
+ ///
+ /// The button will be disabled if both [onPress] and [onLongPress] are null.
final VoidCallback? onLongPress;
/// True if this widget will be selected as the initial focus when no other node in its scope is currently focused.
///
+ /// Defaults to false.
+ ///
/// Ideally, there is only one widget with autofocus set in each FocusScope. If there is more than one widget with
/// autofocus set, then the first one added to the tree will get focus.
- ///
- /// Defaults to false.
final bool autofocus;
/// An optional focus node to use as the focus node for this widget.
@@ -57,10 +72,24 @@ class FButton extends StatelessWidget {
/// The child.
final Widget child;
- /// Creates a [FButton].
+ /// Creates a [FButton] that contains a [prefixIcon], [label]/[rawLabel], and [suffixIcon].
+ ///
+ /// The button layout is as follows, assuming the locale is read from left to right:
+ /// ```
+ /// |---------------------------------------------------|
+ /// | [prefixIcon] [label]/[rawLabel] [suffixIcon] |
+ /// |---------------------------------------------------|
+ /// ```
+ ///
+ /// [FButtonIcon] provides a convenient way to transform a bundled SVG icon into a [prefixIcon] and [suffixIcon].
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * both [label] and [rawLabel] are not null
+ /// * both [label] and [rawLabel] are null
FButton({
required this.onPress,
- this.design = FButtonVariant.primary,
+ this.style = Variant.primary,
this.onLongPress,
this.autofocus = false,
this.focusNode,
@@ -70,19 +99,19 @@ class FButton extends StatelessWidget {
String? label,
Widget? rawLabel,
super.key,
- }) : assert((label != null) ^ (rawLabel != null), 'Either label or rawLabel must be provided, but not both.'),
+ }) : assert((label != null) ^ (rawLabel != null), 'Either "label" or "rawLabel" must be provided, but not both.'),
child = FButtonContent(
prefixIcon: prefixIcon,
suffixIcon: suffixIcon,
- rawLabel: rawLabel,
label: label,
+ rawLabel: rawLabel,
);
- /// Creates a [FButton].
+ /// Creates a [FButton] with custom content.
const FButton.raw({
- required this.design,
required this.onPress,
required this.child,
+ this.style = Variant.primary,
this.onLongPress,
this.autofocus = false,
this.focusNode,
@@ -92,33 +121,33 @@ class FButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
- final style = switch (design) {
- final FButtonStyle style => style,
- FButtonVariant.primary => context.theme.buttonStyles.primary,
- FButtonVariant.secondary => context.theme.buttonStyles.secondary,
- FButtonVariant.outline => context.theme.buttonStyles.outlined,
- FButtonVariant.destructive => context.theme.buttonStyles.destructive,
+ final style = switch (this.style) {
+ final FButtonCustomStyle style => style,
+ Variant.primary => context.theme.buttonStyles.primary,
+ Variant.secondary => context.theme.buttonStyles.secondary,
+ Variant.outline => context.theme.buttonStyles.outline,
+ Variant.destructive => context.theme.buttonStyles.destructive,
};
final enabled = onPress != null || onLongPress != null;
- return _InheritedData(
- data: (style: style, enabled: enabled),
- child: Semantics(
- container: true,
- button: true,
- enabled: enabled,
- child: FocusableActionDetector(
- autofocus: autofocus,
- focusNode: focusNode,
- onFocusChange: onFocusChange,
- child: MouseRegion(
- cursor: onPress == null && onLongPress == null ? MouseCursor.defer : SystemMouseCursors.click,
- child: FTappable(
- onTap: onPress,
- onLongPress: onLongPress,
- child: DecoratedBox(
- decoration: onPress == null && onLongPress == null ? style.disabledBoxDecoration : style.enabledBoxDecoration,
+ return Semantics(
+ container: true,
+ button: true,
+ enabled: enabled,
+ child: FocusableActionDetector(
+ autofocus: autofocus,
+ focusNode: focusNode,
+ onFocusChange: onFocusChange,
+ child: MouseRegion(
+ cursor: enabled ? SystemMouseCursors.click : MouseCursor.defer,
+ child: FTappable(
+ onTap: onPress,
+ onLongPress: onLongPress,
+ child: DecoratedBox(
+ decoration: enabled ? style.enabledBoxDecoration : style.disabledBoxDecoration,
+ child: _InheritedData(
+ data: (style: style, enabled: enabled),
child: child,
),
),
@@ -132,7 +161,7 @@ class FButton extends StatelessWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(DiagnosticsProperty('design', design))
+ ..add(DiagnosticsProperty('style', style))
..add(DiagnosticsProperty('onPress', onPress))
..add(DiagnosticsProperty('onLongPress', onLongPress))
..add(FlagProperty('autofocus', value: autofocus, defaultValue: false, ifTrue: 'autofocus'))
@@ -142,54 +171,84 @@ class FButton extends StatelessWidget {
}
}
-/// The button design. Either a pre-defined [FButtonVariant], or a custom [FButtonStyle].
-sealed class FButtonDesign {}
+/// A [FButton]'s style.
+///
+/// A style can be either one of the pre-defined styles in [FButtonStyle] or a [FButtonCustomStyle]. The pre-defined
+/// styles are a convenient shorthand for the various [FButtonCustomStyle]s in the current context's [FButtonStyles].
+sealed class FButtonStyle {
+ /// The button's primary style.
+ ///
+ /// Shorthand for the current context's [FButtonStyles.primary] style.
+ static const FButtonStyle primary = Variant.primary;
-/// A pre-defined button variant.
-enum FButtonVariant implements FButtonDesign {
- /// A primary-styled button.
- primary,
+ /// The button's secondary style.
+ ///
+ /// Shorthand for the current context's [FButtonStyles.secondary] style.
+ static const FButtonStyle secondary = Variant.secondary;
- /// A secondary-styled button.
- secondary,
+ /// The button's outline style.
+ ///
+ /// Shorthand for the current context's [FButtonStyles.outline] style.
+ static const FButtonStyle outline = Variant.outline;
- /// An outlined button.
- outline,
+ /// The button's destructive style.
+ ///
+ /// Shorthand for the current context's [FButtonStyles.destructive] style.
+ static const FButtonStyle destructive = Variant.destructive;
+}
- /// A destructive button.
+@internal enum Variant implements FButtonStyle {
+ primary,
+ secondary,
+ outline,
destructive,
}
-/// Represents the theme data that is inherited by [FButtonStyle] and used by child [FButton].
-class FButtonStyle extends FButtonDesign with Diagnosticable {
+/// A custom [FButton] style.
+class FButtonCustomStyle extends FButtonStyle with Diagnosticable {
/// The box decoration for an enabled button.
final BoxDecoration enabledBoxDecoration;
/// The box decoration for a disabled button.
final BoxDecoration disabledBoxDecoration;
- /// The content.
+ /// The content's style.
final FButtonContentStyle content;
- /// The icon.
+ /// The icon's style.
final FButtonIconStyle icon;
- /// Creates a [FButtonStyle].
- FButtonStyle({
+ /// Creates a [FButtonCustomStyle].
+ FButtonCustomStyle({
required this.enabledBoxDecoration,
required this.disabledBoxDecoration,
required this.content,
required this.icon,
});
- /// Creates a copy of this [FButtonStyle] with the given properties replaced.
- FButtonStyle copyWith({
+ /// Returns a copy of this [FButtonCustomStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FButtonCustomStyle(
+ /// enabledBoxDecoration: ...,
+ /// disabledBoxDecoration: ...,
+ /// // other properties omitted for brevity
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// disabledBoxDecoration: ...,
+ /// );
+ ///
+ /// print(copy.background); // Colors.blue
+ /// print(copy.border); // Colors.black
+ /// ```
+ @useResult FButtonCustomStyle copyWith({
BoxDecoration? enabledBoxDecoration,
BoxDecoration? disabledBoxDecoration,
FButtonContentStyle? content,
FButtonIconStyle? icon,
}) =>
- FButtonStyle(
+ FButtonCustomStyle(
enabledBoxDecoration: enabledBoxDecoration ?? this.enabledBoxDecoration,
disabledBoxDecoration: disabledBoxDecoration ?? this.disabledBoxDecoration,
content: content ?? this.content,
@@ -209,7 +268,7 @@ class FButtonStyle extends FButtonDesign with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
- other is FButtonStyle &&
+ other is FButtonCustomStyle &&
runtimeType == other.runtimeType &&
enabledBoxDecoration == other.enabledBoxDecoration &&
disabledBoxDecoration == other.disabledBoxDecoration &&
@@ -220,7 +279,7 @@ class FButtonStyle extends FButtonDesign with Diagnosticable {
int get hashCode => enabledBoxDecoration.hashCode ^ disabledBoxDecoration.hashCode ^ content.hashCode ^ icon.hashCode;
}
-typedef _Data = ({FButtonStyle style, bool enabled});
+typedef _Data = ({FButtonCustomStyle style, bool enabled});
class _InheritedData extends InheritedWidget {
final _Data data;
diff --git a/forui/lib/src/widgets/button/button_content.dart b/forui/lib/src/widgets/button/button_content.dart
index 138ad3209..200fb4903 100644
--- a/forui/lib/src/widgets/button/button_content.dart
+++ b/forui/lib/src/widgets/button/button_content.dart
@@ -17,13 +17,12 @@ final class FButtonContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
- final typography = context.theme.typography;
final (:style, :enabled) = FButton._of(context);
return Padding(
padding: style.content.padding,
child: DefaultTextStyle.merge(
- style: enabled ? style.content.enabledText.scale(typography) : style.content.disabledText.scale(typography),
+ style: enabled ? style.content.enabledTextStyle : style.content.disabledTextStyle,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: separate([
@@ -51,47 +50,72 @@ final class FButtonContent extends StatelessWidget {
/// [FButtonContent]'s style.
class FButtonContentStyle with Diagnosticable {
/// The [TextStyle] when this button is enabled.
- final TextStyle enabledText;
+ final TextStyle enabledTextStyle;
/// The [TextStyle] when this button is disabled.
- final TextStyle disabledText;
+ final TextStyle disabledTextStyle;
/// The padding.
final EdgeInsets padding;
/// Creates a [FButtonContentStyle].
FButtonContentStyle({
- required this.enabledText,
- required this.disabledText,
+ required this.enabledTextStyle,
+ required this.disabledTextStyle,
required this.padding,
});
- /// Creates a [FButtonContentStyle] that inherits its properties from the given [foreground] and [disabledForeground].
+ /// Creates a [FButtonContentStyle] that inherits its properties from the given [enabled] and [disabled].
FButtonContentStyle.inherit({
required FTypography typography,
- required Color foreground,
- required Color disabledForeground,
+ required Color enabled,
+ required Color disabled,
}) : padding = const EdgeInsets.symmetric(
horizontal: 16,
vertical: 12.5,
),
- enabledText = TextStyle(
- fontSize: typography.base,
+ enabledTextStyle = typography.base.copyWith(
+ color: enabled,
fontWeight: FontWeight.w500,
- color: foreground,
+ height: 1,
),
- disabledText = TextStyle(
- fontSize: typography.base,
+ disabledTextStyle = typography.base.copyWith(
+ color: disabled,
fontWeight: FontWeight.w500,
- color: disabledForeground,
+ height: 1,
);
+ /// Returns a copy of this [FButtonContentStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FButtonContentStyle(
+ /// enabledTextStyle: ...,
+ /// disabledTextStyle: ...,
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// disabledTextStyle: ...,
+ /// );
+ ///
+ /// print(style.enabledTextStyle == copy.enabledTextStyle); // true
+ /// print(style.disabledTextStyle == copy.disabledTextStyle); // false
+ /// ```
+ @useResult FButtonContentStyle copyWith({
+ TextStyle? enabledTextStyle,
+ TextStyle? disabledTextStyle,
+ EdgeInsets? padding,
+ }) => FButtonContentStyle(
+ enabledTextStyle: enabledTextStyle ?? this.enabledTextStyle,
+ disabledTextStyle: disabledTextStyle ?? this.disabledTextStyle,
+ padding: padding ?? this.padding,
+ );
+
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(DiagnosticsProperty('enabledText', enabledText))
- ..add(DiagnosticsProperty('disabledText', disabledText))
+ ..add(DiagnosticsProperty('enabledTextStyle', enabledTextStyle))
+ ..add(DiagnosticsProperty('disabledTextStyle', disabledTextStyle))
..add(DiagnosticsProperty('padding', padding));
}
@@ -100,10 +124,10 @@ class FButtonContentStyle with Diagnosticable {
identical(this, other) ||
other is FButtonContentStyle &&
runtimeType == other.runtimeType &&
- enabledText == other.enabledText &&
- disabledText == other.disabledText &&
+ enabledTextStyle == other.enabledTextStyle &&
+ disabledTextStyle == other.disabledTextStyle &&
padding == other.padding;
@override
- int get hashCode => enabledText.hashCode ^ disabledText.hashCode ^ padding.hashCode;
+ int get hashCode => enabledTextStyle.hashCode ^ disabledTextStyle.hashCode ^ padding.hashCode;
}
diff --git a/forui/lib/src/widgets/button/button_icon.dart b/forui/lib/src/widgets/button/button_icon.dart
index 463a00dfe..8e7c93caf 100644
--- a/forui/lib/src/widgets/button/button_icon.dart
+++ b/forui/lib/src/widgets/button/button_icon.dart
@@ -1,20 +1,20 @@
part of 'button.dart';
-/// Represents an icon that is used in a [FButton].
+/// A [FButton]'s icon.
class FButtonIcon extends StatelessWidget {
/// The icon.
final SvgAsset icon;
- /// Creates a [FButtonIcon].
+ /// Creates a [FButtonIcon] from the given SVG [icon].
const FButtonIcon({required this.icon, super.key});
@override
Widget build(BuildContext context) {
- final (:style, :enabled) = FButton._of(context);
+ final (style: FButtonCustomStyle(:icon), :enabled) = FButton._of(context);
- return icon(
- height: 20,
- colorFilter: ColorFilter.mode(enabled ? style.icon.enabled : style.icon.disabled, BlendMode.srcIn),
+ return this.icon(
+ height: icon.height,
+ colorFilter: ColorFilter.mode(enabled ? icon.enabledColor : icon.disabledColor, BlendMode.srcIn),
);
}
@override
@@ -27,36 +27,60 @@ class FButtonIcon extends StatelessWidget {
/// [FButtonIcon]'s style.
final class FButtonIconStyle with Diagnosticable {
/// The icon's color when this button is enabled.
- final Color enabled;
+ final Color enabledColor;
/// The icon's color when this button is disabled.
- final Color disabled;
+ final Color disabledColor;
/// The icon's height. Defaults to 20.
final double height;
/// Creates a [FButtonIconStyle].
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * `height` <= 0.0
+ /// * `height` is Nan
FButtonIconStyle({
- required this.enabled,
- required this.disabled,
- required this.height,
- });
+ required this.enabledColor,
+ required this.disabledColor,
+ this.height = 20,
+ }):
+ assert(0 < height, 'The height is $height, but it should be in the range "0 < height".');
- /// Creates a [FButtonIconStyle] that inherits its properties from the given [foreground] and [disabledForeground].
- FButtonIconStyle.inherit({
- required Color foreground,
- required Color disabledForeground,
- }) : enabled = foreground,
- disabled = disabledForeground,
- height = 20;
+
+ /// Returns a copy of this [FBadgeContentStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FButtonIconStyle(
+ /// enabledColor: Colors.red,
+ /// disabledColor: Colors.black,
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// disabledColor: Colors.blue,
+ /// );
+ ///
+ /// print(copy.enabledColor); // Colors.blue
+ /// print(copy.disabledColor); // Colors.black
+ /// ```
+ @useResult FButtonIconStyle copyWith({
+ Color? enabledColor,
+ Color? disabledColor,
+ double? height,
+ }) => FButtonIconStyle(
+ enabledColor: enabledColor ?? this.enabledColor,
+ disabledColor: disabledColor ?? this.disabledColor,
+ height: height ?? this.height,
+ );
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(ColorProperty('enabled', enabled))
- ..add(ColorProperty('disabled', disabled))
- ..add(DoubleProperty('height', height));
+ ..add(ColorProperty('enabledColor', enabledColor))
+ ..add(ColorProperty('disabledColor', disabledColor))
+ ..add(DoubleProperty('height', height, defaultValue: 20));
}
@override
@@ -64,10 +88,10 @@ final class FButtonIconStyle with Diagnosticable {
identical(this, other) ||
other is FButtonIconStyle &&
runtimeType == other.runtimeType &&
- enabled == other.enabled &&
- disabled == other.disabled &&
+ enabledColor == other.enabledColor &&
+ disabledColor == other.disabledColor &&
height == other.height;
@override
- int get hashCode => enabled.hashCode ^ disabled.hashCode ^ height.hashCode;
+ int get hashCode => enabledColor.hashCode ^ disabledColor.hashCode ^ height.hashCode;
}
diff --git a/forui/lib/src/widgets/button/button_styles.dart b/forui/lib/src/widgets/button/button_styles.dart
index c90303c3f..fd6fabd4c 100644
--- a/forui/lib/src/widgets/button/button_styles.dart
+++ b/forui/lib/src/widgets/button/button_styles.dart
@@ -1,30 +1,31 @@
part of 'button.dart';
-/// [FButtonStyle]'s style.
+/// [FButtonCustomStyle]'s style.
class FButtonStyles with Diagnosticable {
- /// The primary style.
- final FButtonStyle primary;
+ /// The primary button style.
+ final FButtonCustomStyle primary;
- /// The secondary style.
- final FButtonStyle secondary;
+ /// The secondary button style.
+ final FButtonCustomStyle secondary;
- /// The destructive style.
- final FButtonStyle destructive;
+ /// The destructive button style.
+ final FButtonCustomStyle destructive;
- /// The outlined style.
- final FButtonStyle outlined;
+ /// The outlined button style.
+ final FButtonCustomStyle outline;
- /// Creates a [FButtonStyle].
+ /// Creates a [FButtonCustomStyle].
const FButtonStyles({
required this.primary,
required this.secondary,
required this.destructive,
- required this.outlined,
+ required this.outline,
});
- /// Creates a [FButtonStyle] that inherits its properties from [colorScheme].
+ /// Creates a [FButtonCustomStyle] that inherits its properties from the provided [colorScheme], [typography], and
+ /// [style].
FButtonStyles.inherit({required FColorScheme colorScheme, required FTypography typography, required FStyle style})
- : primary = FButtonStyle(
+ : primary = FButtonCustomStyle(
enabledBoxDecoration: BoxDecoration(
borderRadius: style.borderRadius,
color: colorScheme.primary,
@@ -35,15 +36,15 @@ class FButtonStyles with Diagnosticable {
),
content: FButtonContentStyle.inherit(
typography: typography,
- foreground: colorScheme.primaryForeground,
- disabledForeground: colorScheme.primaryForeground.withOpacity(0.5),
+ enabled: colorScheme.primaryForeground,
+ disabled: colorScheme.primaryForeground.withOpacity(0.5),
),
- icon: FButtonIconStyle.inherit(
- foreground: colorScheme.primaryForeground,
- disabledForeground: colorScheme.primaryForeground.withOpacity(0.5),
+ icon: FButtonIconStyle(
+ enabledColor: colorScheme.primaryForeground,
+ disabledColor: colorScheme.primaryForeground.withOpacity(0.5),
),
),
- secondary = FButtonStyle(
+ secondary = FButtonCustomStyle(
enabledBoxDecoration: BoxDecoration(
borderRadius: style.borderRadius,
color: colorScheme.secondary,
@@ -54,15 +55,15 @@ class FButtonStyles with Diagnosticable {
),
content: FButtonContentStyle.inherit(
typography: typography,
- foreground: colorScheme.secondaryForeground,
- disabledForeground: colorScheme.secondaryForeground.withOpacity(0.5),
+ enabled: colorScheme.secondaryForeground,
+ disabled: colorScheme.secondaryForeground.withOpacity(0.5),
),
- icon: FButtonIconStyle.inherit(
- foreground: colorScheme.secondaryForeground,
- disabledForeground: colorScheme.secondaryForeground.withOpacity(0.5),
+ icon: FButtonIconStyle(
+ enabledColor: colorScheme.secondaryForeground,
+ disabledColor: colorScheme.secondaryForeground.withOpacity(0.5),
),
),
- destructive = FButtonStyle(
+ destructive = FButtonCustomStyle(
enabledBoxDecoration: BoxDecoration(
borderRadius: style.borderRadius,
color: colorScheme.destructive,
@@ -73,15 +74,15 @@ class FButtonStyles with Diagnosticable {
),
content: FButtonContentStyle.inherit(
typography: typography,
- foreground: colorScheme.destructiveForeground,
- disabledForeground: colorScheme.destructiveForeground.withOpacity(0.5),
+ enabled: colorScheme.destructiveForeground,
+ disabled: colorScheme.destructiveForeground.withOpacity(0.5),
),
- icon: FButtonIconStyle.inherit(
- foreground: colorScheme.destructiveForeground,
- disabledForeground: colorScheme.destructiveForeground.withOpacity(0.5),
+ icon: FButtonIconStyle(
+ enabledColor: colorScheme.destructiveForeground,
+ disabledColor: colorScheme.destructiveForeground.withOpacity(0.5),
),
),
- outlined = FButtonStyle(
+ outline = FButtonCustomStyle(
enabledBoxDecoration: BoxDecoration(
border: Border.all(
color: colorScheme.border,
@@ -96,15 +97,42 @@ class FButtonStyles with Diagnosticable {
),
content: FButtonContentStyle.inherit(
typography: typography,
- foreground: colorScheme.secondaryForeground,
- disabledForeground: colorScheme.secondaryForeground.withOpacity(0.5),
+ enabled: colorScheme.secondaryForeground,
+ disabled: colorScheme.secondaryForeground.withOpacity(0.5),
),
- icon: FButtonIconStyle.inherit(
- foreground: colorScheme.secondaryForeground,
- disabledForeground: colorScheme.secondaryForeground.withOpacity(0.5),
+ icon: FButtonIconStyle(
+ enabledColor: colorScheme.secondaryForeground,
+ disabledColor: colorScheme.secondaryForeground.withOpacity(0.5),
),
);
+ /// Returns a copy of this [FButtonStyles] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FButtonStyles(
+ /// primary: ...,
+ /// secondary: ...,
+ /// // Other arguments omitted for brevity
+ /// );
+ ///
+ /// final copy = style.copyWith(secondary: ...);
+ ///
+ /// print(style.primary == copy.primary); // true
+ /// print(style.secondary == copy.secondary); // false
+ /// ```
+ @useResult FButtonStyles copyWith({
+ FButtonCustomStyle? primary,
+ FButtonCustomStyle? secondary,
+ FButtonCustomStyle? destructive,
+ FButtonCustomStyle? outline,
+ }) =>
+ FButtonStyles(
+ primary: primary ?? this.primary,
+ secondary: secondary ?? this.secondary,
+ destructive: destructive ?? this.destructive,
+ outline: outline ?? this.outline,
+ );
+
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
@@ -112,7 +140,7 @@ class FButtonStyles with Diagnosticable {
..add(DiagnosticsProperty('primary', primary))
..add(DiagnosticsProperty('secondary', secondary))
..add(DiagnosticsProperty('destructive', destructive))
- ..add(DiagnosticsProperty('outlined', outlined));
+ ..add(DiagnosticsProperty('outlined', outline));
}
@override
@@ -123,8 +151,8 @@ class FButtonStyles with Diagnosticable {
primary == other.primary &&
secondary == other.secondary &&
destructive == other.destructive &&
- outlined == other.outlined;
+ outline == other.outline;
@override
- int get hashCode => primary.hashCode ^ secondary.hashCode ^ destructive.hashCode ^ outlined.hashCode;
+ int get hashCode => primary.hashCode ^ secondary.hashCode ^ destructive.hashCode ^ outline.hashCode;
}
diff --git a/forui/lib/src/widgets/card/card.dart b/forui/lib/src/widgets/card/card.dart
index 2fa0d6323..1fb722fda 100644
--- a/forui/lib/src/widgets/card/card.dart
+++ b/forui/lib/src/widgets/card/card.dart
@@ -7,7 +7,13 @@ import 'package:forui/forui.dart';
part 'card_content.dart';
-/// A card widget.
+/// A card.
+///
+/// Card are typically used to group related information together.
+///
+/// See:
+/// * https://forui.dev/docs/card for working examples.
+/// * [FCardStyle] for customizing a card's appearance.
final class FCard extends StatelessWidget {
/// The style. Defaults to [FThemeData.cardStyle].
final FCardStyle? style;
@@ -15,7 +21,22 @@ final class FCard extends StatelessWidget {
/// The child.
final Widget child;
- /// Creates a [FCard] with a tile and subtitle.
+ /// Creates a [FCard] with a tile, subtitle, and [child].
+ ///
+ /// The card's layout is as follows:
+ /// ```
+ /// |---------------------------|
+ /// | [title]/[rawTitle] |
+ /// | [subtitle]/[rawSubTitle] |
+ /// | |
+ /// | [child] |
+ /// |---------------------------|
+ /// ```
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * [title] and [rawTitle] are both not null.
+ /// * [subtitle] and [rawSubtitle] are both not null.
FCard({
String? title,
Widget? rawTitle,
@@ -28,15 +49,15 @@ final class FCard extends StatelessWidget {
assert(title == null || rawTitle == null, 'Cannot provide both a title and a rawTitle.'),
assert(subtitle == null || rawSubtitle == null, 'Cannot provide both a subtitle and a rawSubtitle.'),
child = FCardContent(
- title: title,
- rawTitle: rawTitle,
- subtitle: subtitle,
- rawSubtitle: rawSubtitle,
- style: style?.content,
- child: child,
- );
-
- /// Creates a [FCard].
+ title: title,
+ rawTitle: rawTitle,
+ subtitle: subtitle,
+ rawSubtitle: rawSubtitle,
+ style: style?.content,
+ child: child,
+ );
+
+ /// Creates a [FCard] with custom content.
const FCard.raw({required this.child, this.style, super.key});
@override
@@ -50,12 +71,10 @@ final class FCard extends StatelessWidget {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty('style', style));
}
-
}
/// [FCard]'s style.
final class FCardStyle with Diagnosticable {
-
/// The decoration.
final BoxDecoration decoration;
@@ -74,8 +93,20 @@ final class FCardStyle with Diagnosticable {
),
content = FCardContentStyle.inherit(colorScheme: colorScheme, typography: typography);
- /// Creates a copy of this [FCardStyle] with the given properties replaced.
- FCardStyle copyWith({BoxDecoration? decoration, FCardContentStyle? content}) => FCardStyle(
+ /// Returns a copy of this [FCardStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FCardStyle(
+ /// decoration: ...,
+ /// content: ...,
+ /// );
+ ///
+ /// final copy = style.copyWith(content: ...);
+ ///
+ /// print(style.decoration == copy.decoration); // true
+ /// print(style.content == copy.content); // false
+ /// ```
+ @useResult FCardStyle copyWith({BoxDecoration? decoration, FCardContentStyle? content}) => FCardStyle(
decoration: decoration ?? this.decoration,
content: content ?? this.content,
);
diff --git a/forui/lib/src/widgets/card/card_content.dart b/forui/lib/src/widgets/card/card_content.dart
index fda26f712..730ba9afa 100644
--- a/forui/lib/src/widgets/card/card_content.dart
+++ b/forui/lib/src/widgets/card/card_content.dart
@@ -1,6 +1,7 @@
part of 'card.dart';
-@internal final class FCardContent extends StatelessWidget {
+@internal
+final class FCardContent extends StatelessWidget {
final String? title;
final Widget? rawTitle;
final String? subtitle;
@@ -13,28 +14,27 @@ part of 'card.dart';
this.rawTitle,
this.subtitle,
this.rawSubtitle,
- this.child,
- this.style,
+ this.child,
+ this.style,
super.key,
});
@override
Widget build(BuildContext context) {
- final typography = context.theme.typography;
final style = this.style ?? context.theme.cardStyle.content;
-
+
final title = switch ((this.title, rawTitle)) {
(final String title, _) => Text(title),
(_, final Widget title) => title,
_ => null,
};
-
+
final subtitle = switch ((this.subtitle, rawSubtitle)) {
(final String subtitle, _) => Text(subtitle),
(_, final Widget subtitle) => subtitle,
_ => null,
};
-
+
return Padding(
padding: style.padding,
child: Column(
@@ -42,19 +42,18 @@ part of 'card.dart';
children: [
if (title != null)
DefaultTextStyle.merge(
- style: style.title.scale(typography),
+ style: style.titleTextStyle,
child: title,
),
-
if (subtitle != null)
DefaultTextStyle.merge(
- style: style.subtitle.scale(typography),
+ style: style.subtitleTextStyle,
child: subtitle,
),
-
if (child != null)
Padding(
- padding: (title == null && subtitle == null) ? const EdgeInsets.only(top: 4) : const EdgeInsets.only(top: 10),
+ padding:
+ (title == null && subtitle == null) ? const EdgeInsets.only(top: 4) : const EdgeInsets.only(top: 10),
child: child!,
),
],
@@ -74,55 +73,73 @@ part of 'card.dart';
/// A card content's style.
final class FCardContentStyle with Diagnosticable {
+ /// The title's [TextStyle].
+ final TextStyle titleTextStyle;
- /// The padding.
- final EdgeInsets padding;
-
- /// The title.
- final TextStyle title;
+ /// The subtitle's [TextStyle].
+ final TextStyle subtitleTextStyle;
- /// The subtitle.
- final TextStyle subtitle;
+ /// The padding. Defaults to `EdgeInsets.fromLTRB(16, 12, 16, 16)`.
+ final EdgeInsets padding;
/// Creates a [FCardContentStyle].
- const FCardContentStyle({required this.padding, required this.title, required this.subtitle});
+ const FCardContentStyle({
+ required this.titleTextStyle,
+ required this.subtitleTextStyle,
+ this.padding = const EdgeInsets.fromLTRB(16, 12, 16, 16),
+ });
/// Creates a [FCardContentStyle] that inherits its properties from [colorScheme] and [typography].
- FCardContentStyle.inherit({required FColorScheme colorScheme, required FTypography typography}):
- padding = const EdgeInsets.fromLTRB(16, 12, 16, 16),
- title = TextStyle(
- fontSize: typography.base,
- fontWeight: FontWeight.w600,
- color: colorScheme.foreground,
- ),
- subtitle = TextStyle(
- fontSize: typography.sm,
- color: colorScheme.mutedForeground,
- );
+ FCardContentStyle.inherit({required FColorScheme colorScheme, required FTypography typography})
+ : titleTextStyle = typography.base.copyWith(
+ fontWeight: FontWeight.w600,
+ color: colorScheme.foreground,
+ ),
+ subtitleTextStyle = typography.sm.copyWith(color: colorScheme.mutedForeground),
+ padding = const EdgeInsets.fromLTRB(16, 12, 16, 16);
- /// Creates a copy of this [FCardContentStyle] with the given properties replaced.
- FCardContentStyle copyWith({EdgeInsets? padding, TextStyle? title, TextStyle? subtitle}) => FCardContentStyle(
- padding: padding ?? this.padding,
- title: title ?? this.title,
- subtitle: subtitle ?? this.subtitle,
- );
+ /// Returns a copy of this [FCardContentStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FCardContentStyle(
+ /// titleTextStyle: ...,
+ /// subtitleTextStyle: ...,
+ /// );
+ ///
+ /// final copy = style.copyWith(titleTextStyle: ...);
+ ///
+ /// print(style.titleTextStyle == copy.titleTextStyle); // true
+ /// print(style.subtitleTextStyle == copy.subtitleTextStyle); // false
+ /// ```
+ FCardContentStyle copyWith({
+ TextStyle? titleTextStyle,
+ TextStyle? subtitleTextStyle,
+ EdgeInsets? padding,
+ }) =>
+ FCardContentStyle(
+ titleTextStyle: titleTextStyle ?? this.titleTextStyle,
+ subtitleTextStyle: subtitleTextStyle ?? this.subtitleTextStyle,
+ padding: padding ?? this.padding,
+ );
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(DiagnosticsProperty('padding', padding))
- ..add(DiagnosticsProperty('title', title))
- ..add(DiagnosticsProperty('subtitle', subtitle));
+ ..add(DiagnosticsProperty('title', titleTextStyle))
+ ..add(DiagnosticsProperty('subtitle', subtitleTextStyle))
+ ..add(DiagnosticsProperty('padding', padding));
}
@override
- bool operator ==(Object other) => identical(this, other) || other is FCardContentStyle &&
- runtimeType == other.runtimeType &&
- padding == other.padding &&
- title == other.title &&
- subtitle == other.subtitle;
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is FCardContentStyle &&
+ runtimeType == other.runtimeType &&
+ titleTextStyle == other.titleTextStyle &&
+ subtitleTextStyle == other.subtitleTextStyle &&
+ padding == other.padding;
@override
- int get hashCode => padding.hashCode ^ title.hashCode ^ subtitle.hashCode;
+ int get hashCode => titleTextStyle.hashCode ^ subtitleTextStyle.hashCode ^ padding.hashCode;
}
diff --git a/forui/lib/src/widgets/dialog/dialog.dart b/forui/lib/src/widgets/dialog/dialog.dart
index c3b1b736d..d75665f67 100644
--- a/forui/lib/src/widgets/dialog/dialog.dart
+++ b/forui/lib/src/widgets/dialog/dialog.dart
@@ -9,27 +9,25 @@ import 'package:forui/forui.dart';
part 'dialog_content.dart';
-/// The alignment of the actions in a dialog.
-enum FDialogAlignment {
- /// Aligns the actions horizontally. This should be preferred on devices with wider screens, i.e. desktops.
- horizontal,
- /// Aligns the actions vertically. This should be preferred on devices with small screens, i.e. mobile devices.
- vertical,
-}
-
-/// A modal dialog that interrupts the user with important content and expects a response.
+/// A modal dialog.
+///
+/// A dialog interrupts the user with important content and expects a response. It is typically used with
+/// [showAdaptiveDialog] and [showDialog].
+///
+/// See:
+/// * https://forui.dev/docs/dialog for working examples.
+/// * [FDialogStyle] for customizing a dialog's appearance.
class FDialog extends StatelessWidget {
- /// The dialog's style.
+ /// The dialog's style. Defaults to [FThemeData.dialogStyle].
final FDialogStyle? style;
- /// The duration of the animation to show when the system keyboard intrudes
- /// into the space that the dialog is placed in.
+ /// The duration of the animation to show when the system keyboard intrudes into the space that the dialog is placed in.
///
/// Defaults to 100 milliseconds.
final Duration insetAnimationDuration;
- /// The curve to use for the animation shown when the system keyboard intrudes
- /// into the space that the dialog is placed in.
+ /// The curve to use for the animation shown when the system keyboard intrudes into the space that the dialog is
+ /// placed in.
///
/// Defaults to [Curves.decelerate].
final Curve insetAnimationCurve;
@@ -38,14 +36,45 @@ class FDialog extends StatelessWidget {
/// is opened and closed.
///
/// See also:
- /// * [SemanticsConfiguration.namesRoute], for a description of how this
- /// value is used.
+ /// * [SemanticsConfiguration.namesRoute], for a description of how this value is used.
final String? semanticLabel;
- /// The builder.
+ /// The builder for the dialog's content.
final Widget Function(BuildContext, FDialogStyle) builder;
/// Creates a [FDialog] with a title, subtitle, and possible actions.
+ ///
+ /// The [semanticLabel] defaults to [title] if it is not provided.
+ ///
+ /// The [direction] determines the layout of the actions. It is recommended to use [Axis.vertical] on smaller devices,
+ /// such as mobile phones, and [Axis.horizontal] on larger devices, such as tablets and desktops.
+ ///
+ /// The [Axis.vertical] layout with two possibles actions is:
+ /// ```
+ /// |--------------------|
+ /// | [title]/[rawTitle] |
+ /// | |
+ /// | [body]/[rawBody] |
+ /// | |
+ /// | [first action] |
+ /// | [second action] |
+ /// |--------------------|
+ /// ```
+ ///
+ /// The [Axis.horizontal] layout with two possibles actions is:
+ /// ```
+ /// |--------------------------------------------|
+ /// | [title]/[rawTitle] |
+ /// | |
+ /// | [body]/[rawBody] |
+ /// | |
+ /// | [first action] [second action] |
+ /// |--------------------------------------------|
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * [title] and [rawTitle] are both not null
+ /// * [body] and [rawBody] are both not null
FDialog({
required List actions,
this.style,
@@ -56,30 +85,29 @@ class FDialog extends StatelessWidget {
Widget? rawTitle,
String? body,
Widget? rawBody,
- FDialogAlignment alignment = FDialogAlignment.vertical,
+ Axis direction = Axis.vertical,
super.key,
- }):
- assert(title == null || rawTitle == null, 'Cannot provide both a title and a rawTitle.'),
- assert(body == null || rawBody == null, 'Cannot provide both a body and a rawBody.'),
- semanticLabel = semanticLabel ?? title,
- builder = switch (alignment) {
- FDialogAlignment.horizontal => (context, style) => FHorizontalDialogContent(
- style: style.horizontal,
- title: title,
- rawTitle: rawTitle,
- body: body,
- rawBody: rawBody,
- actions: actions,
- ),
- FDialogAlignment.vertical => (context, style) => FVerticalDialogContent(
- style: style.vertical,
- title: title,
- rawTitle: rawTitle,
- body: body,
- rawBody: rawBody,
- actions: actions,
- ),
- };
+ }) : assert(title == null || rawTitle == null, 'Cannot provide both a title and a rawTitle.'),
+ assert(body == null || rawBody == null, 'Cannot provide both a body and a rawBody.'),
+ semanticLabel = semanticLabel ?? title,
+ builder = switch (direction) {
+ Axis.horizontal => (context, style) => FHorizontalDialogContent(
+ style: style.horizontal,
+ title: title,
+ rawTitle: rawTitle,
+ body: body,
+ rawBody: rawBody,
+ actions: actions,
+ ),
+ Axis.vertical => (context, style) => FVerticalDialogContent(
+ style: style.vertical,
+ title: title,
+ rawTitle: rawTitle,
+ body: body,
+ rawBody: rawBody,
+ actions: actions,
+ ),
+ };
/// Creates a [FDialog] with a custom builder.
const FDialog.raw({
@@ -94,8 +122,8 @@ class FDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = context.theme;
- final style = this.style ?? theme.dialogStyle;
final typography = theme.typography;
+ final style = this.style ?? theme.dialogStyle;
return AnimatedPadding(
padding: MediaQuery.viewInsetsOf(context) + style.insetPadding,
@@ -108,11 +136,8 @@ class FDialog extends StatelessWidget {
removeBottom: true,
context: context,
child: Align(
- child: DefaultTextStyle(
- style: context.theme.typography.toTextStyle(
- fontSize: typography.base,
- color: context.theme.colorScheme.foreground,
- ),
+ child: DefaultTextStyle.merge(
+ style: typography.base.copyWith(color: theme.colorScheme.foreground),
child: Semantics(
scopesRoute: true,
explicitChildNodes: true,
@@ -140,19 +165,20 @@ class FDialog extends StatelessWidget {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty('style', style))
- ..add(DiagnosticsProperty('insetAnimationDuration', insetAnimationDuration))
- ..add(DiagnosticsProperty('insetAnimationCurve', insetAnimationCurve))
+ ..add(DiagnosticsProperty('insetAnimationDuration', insetAnimationDuration,
+ defaultValue: const Duration(milliseconds: 100)))
+ ..add(DiagnosticsProperty('insetAnimationCurve', insetAnimationCurve, defaultValue: Curves.decelerate))
..add(StringProperty('semanticLabel', semanticLabel))
..add(DiagnosticsProperty('builder', builder));
}
}
-/// The [FDialog]'s style.
+/// [FDialog]'s style.
final class FDialogStyle with Diagnosticable {
/// The decoration.
final BoxDecoration decoration;
- /// The inset padding. Defaults to `EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0)`.
+ /// The inset padding. Defaults to `EdgeInsets.symmetric(horizontal: 40, vertical: 24)`.
final EdgeInsets insetPadding;
/// The horizontal dialog content's style.
@@ -161,10 +187,10 @@ final class FDialogStyle with Diagnosticable {
/// The vertical dialog content's style.
final FDialogContentStyle vertical;
- /// The minimum width of the dialog. Defaults to 280.0.
+ /// The minimum width of the dialog. Defaults to 280.
final double minWidth;
- /// The maximum width of the dialog. Defaults to 560.0.
+ /// The maximum width of the dialog. Defaults to 560.
final double maxWidth;
/// Creates a [FDialogStyle].
@@ -174,30 +200,64 @@ final class FDialogStyle with Diagnosticable {
required this.vertical,
this.minWidth = 280.0,
this.maxWidth = 560.0,
- this.insetPadding = const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),
+ this.insetPadding = const EdgeInsets.symmetric(horizontal: 40, vertical: 24),
});
- /// Creates a [FDialogStyle] that inherits its properties from [colorScheme].
- FDialogStyle.inherit({required FStyle style, required FColorScheme colorScheme, required FTypography typography}):
- decoration = BoxDecoration(
- borderRadius: style.borderRadius,
- color: colorScheme.background,
- ),
- insetPadding = const EdgeInsets.symmetric(horizontal: 40, vertical: 24),
- horizontal = FDialogContentStyle.inherit(
- colorScheme: colorScheme,
- typography: typography,
- padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 25),
- actionPadding: 7,
- ),
- vertical = FDialogContentStyle.inherit(
- colorScheme: colorScheme,
- typography: typography,
- padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 25),
- actionPadding: 8,
- ),
- minWidth = 280.0,
- maxWidth = 560.0;
+ /// Creates a [FDialogStyle] that inherits its properties from the given [style], [colorScheme], and [typography].
+ FDialogStyle.inherit({required FStyle style, required FColorScheme colorScheme, required FTypography typography})
+ : decoration = BoxDecoration(
+ borderRadius: style.borderRadius,
+ color: colorScheme.background,
+ ),
+ insetPadding = const EdgeInsets.symmetric(horizontal: 40, vertical: 24),
+ horizontal = FDialogContentStyle.inherit(
+ colorScheme: colorScheme,
+ typography: typography,
+ padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 25),
+ actionPadding: 7,
+ ),
+ vertical = FDialogContentStyle.inherit(
+ colorScheme: colorScheme,
+ typography: typography,
+ padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 25),
+ actionPadding: 8,
+ ),
+ minWidth = 280,
+ maxWidth = 560;
+
+ /// Returns a copy of this [FButtonCustomStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FDialogStyle(
+ /// minWidth: 1,
+ /// maxWidth: 2,
+ /// // other properties omitted for brevity
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// maxWidth: 3,
+ /// );
+ ///
+ /// print(copy.minWidth); // 1
+ /// print(copy.maxWidth); // 3
+ /// ```
+ @useResult
+ FDialogStyle copyWith({
+ BoxDecoration? decoration,
+ EdgeInsets? insetPadding,
+ FDialogContentStyle? horizontal,
+ FDialogContentStyle? vertical,
+ double? minWidth,
+ double? maxWidth,
+ }) =>
+ FDialogStyle(
+ decoration: decoration ?? this.decoration,
+ insetPadding: insetPadding ?? this.insetPadding,
+ horizontal: horizontal ?? this.horizontal,
+ vertical: vertical ?? this.vertical,
+ minWidth: minWidth ?? this.minWidth,
+ maxWidth: maxWidth ?? this.maxWidth,
+ );
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
@@ -207,7 +267,7 @@ final class FDialogStyle with Diagnosticable {
..add(DiagnosticsProperty('insetPadding', insetPadding))
..add(DiagnosticsProperty('horizontal', horizontal))
..add(DiagnosticsProperty('vertical', vertical))
- ..add(DoubleProperty('minWidth', minWidth, defaultValue: 280.0))
- ..add(DoubleProperty('maxWidth', maxWidth, defaultValue: 560.0));
+ ..add(DoubleProperty('minWidth', minWidth, defaultValue: 280))
+ ..add(DoubleProperty('maxWidth', maxWidth, defaultValue: 560));
}
}
diff --git a/forui/lib/src/widgets/dialog/dialog_content.dart b/forui/lib/src/widgets/dialog/dialog_content.dart
index f43be3562..b35ce352f 100644
--- a/forui/lib/src/widgets/dialog/dialog_content.dart
+++ b/forui/lib/src/widgets/dialog/dialog_content.dart
@@ -1,6 +1,7 @@
part of 'dialog.dart';
-@internal sealed class FDialogContent extends StatelessWidget {
+@internal
+sealed class FDialogContent extends StatelessWidget {
final FDialogContentStyle style;
final CrossAxisAlignment alignment;
final String? title;
@@ -12,7 +13,7 @@ part of 'dialog.dart';
final List actions;
const FDialogContent({
- required this.style,
+ required this.style,
required this.alignment,
required this.title,
required this.titleTextAlign,
@@ -23,23 +24,21 @@ part of 'dialog.dart';
required this.actions,
super.key,
});
-
+
@override
Widget build(BuildContext context) {
- final typography = context.theme.typography;
-
final title = switch ((this.title, rawTitle)) {
(final String title, _) => Text(title),
(_, final Widget title) => title,
_ => null,
};
-
+
final body = switch ((this.body, rawBody)) {
(final String body, _) => Text(body),
(_, final Widget body) => body,
_ => null,
};
-
+
return IntrinsicWidth(
child: Padding(
padding: style.padding,
@@ -54,7 +53,7 @@ part of 'dialog.dart';
container: true,
child: DefaultTextStyle.merge(
textAlign: titleTextAlign,
- style: style.title.scale(typography),
+ style: style.titleTextStyle,
child: title,
),
),
@@ -66,7 +65,7 @@ part of 'dialog.dart';
container: true,
child: DefaultTextStyle.merge(
textAlign: bodyTextAlign,
- style: style.body.scale(typography),
+ style: style.bodyTextStyle,
child: body,
),
),
@@ -77,7 +76,7 @@ part of 'dialog.dart';
),
);
}
-
+
Widget _actions(BuildContext context);
@override
@@ -94,7 +93,8 @@ part of 'dialog.dart';
}
}
-@internal class FHorizontalDialogContent extends FDialogContent {
+@internal
+class FHorizontalDialogContent extends FDialogContent {
const FHorizontalDialogContent({
required super.style,
required super.title,
@@ -102,29 +102,22 @@ part of 'dialog.dart';
required super.body,
required super.rawBody,
required super.actions,
- }): super(
- alignment: CrossAxisAlignment.start,
- titleTextAlign: TextAlign.start,
- bodyTextAlign: TextAlign.start
- );
+ }) : super(alignment: CrossAxisAlignment.start, titleTextAlign: TextAlign.start, bodyTextAlign: TextAlign.start);
@override
Widget _actions(BuildContext context) => Row(
- mainAxisAlignment: MainAxisAlignment.end,
- children: separate(
- [
- for (final action in actions)
- IntrinsicWidth(
- child: action,
- ),
- ],
- by: [ SizedBox(width: style.actionPadding) ],
- ),
- );
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: separate(
+ [
+ for (final action in actions) IntrinsicWidth(child: action),
+ ],
+ by: [SizedBox(width: style.actionPadding)],
+ ),
+ );
}
-
-@internal class FVerticalDialogContent extends FDialogContent {
+@internal
+class FVerticalDialogContent extends FDialogContent {
const FVerticalDialogContent({
required super.style,
required super.title,
@@ -132,68 +125,89 @@ part of 'dialog.dart';
required super.body,
required super.rawBody,
required super.actions,
- }): super(
- alignment: CrossAxisAlignment.center,
- titleTextAlign: TextAlign.center,
- bodyTextAlign: TextAlign.center
- );
+ }) : super(alignment: CrossAxisAlignment.center, titleTextAlign: TextAlign.center, bodyTextAlign: TextAlign.center);
@override
Widget _actions(BuildContext context) => Column(
- mainAxisSize: MainAxisSize.min,
- children: separate(
- actions,
- by: [ SizedBox(height: style.actionPadding) ],
- ),
- );
+ mainAxisSize: MainAxisSize.min,
+ children: separate(
+ actions,
+ by: [SizedBox(height: style.actionPadding)],
+ ),
+ );
}
/// The dialog content's style.
final class FDialogContentStyle with Diagnosticable {
- /// The padding surrounding the content.
- final EdgeInsets padding;
+ /// The title's [TextStyle].
+ final TextStyle titleTextStyle;
- /// The title style.
- final TextStyle title;
+ /// The body's [TextStyle].
+ final TextStyle bodyTextStyle;
- /// The body style.
- final TextStyle body;
+ /// The padding surrounding the content.
+ final EdgeInsets padding;
- /// The padding between actions.
+ /// The space between actions.
final double actionPadding;
-
+
/// Creates a [FDialogContentStyle].
FDialogContentStyle({
+ required this.titleTextStyle,
+ required this.bodyTextStyle,
required this.padding,
- required this.title,
- required this.body,
required this.actionPadding,
});
-
+
/// Creates a [FDialogContentStyle] that inherits its properties from [colorScheme] and [typography].
FDialogContentStyle.inherit({
required FColorScheme colorScheme,
required FTypography typography,
required this.padding,
required this.actionPadding,
- }):
- title = TextStyle(
- fontSize: typography.lg,
- fontWeight: FontWeight.w600,
- color: colorScheme.foreground,
- ),
- body = TextStyle(
- fontSize: typography.sm,
- color: colorScheme.mutedForeground,
- );
+ }) : titleTextStyle = typography.lg.copyWith(
+ fontWeight: FontWeight.w600,
+ color: colorScheme.foreground,
+ ),
+ bodyTextStyle = typography.sm.copyWith(color: colorScheme.mutedForeground);
+
+ /// Returns a copy of this [FDialogContentStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FDialogContentStyle(
+ /// titleTextStyle: ...,
+ /// bodyTextStyle: ...,
+ /// // other properties omitted for brevity
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// bodyTextStyle: ...,
+ /// );
+ ///
+ /// print(style.titleTextStyle == copy.titleTextStyle); // true
+ /// print(style.bodyTextStyle == copy.bodyTextStyle); // false
+ /// ```
+ @useResult
+ FDialogContentStyle copyWith({
+ TextStyle? titleTextStyle,
+ TextStyle? bodyTextStyle,
+ EdgeInsets? padding,
+ double? actionPadding,
+ }) =>
+ FDialogContentStyle(
+ titleTextStyle: titleTextStyle ?? this.titleTextStyle,
+ bodyTextStyle: bodyTextStyle ?? this.bodyTextStyle,
+ padding: padding ?? this.padding,
+ actionPadding: actionPadding ?? this.actionPadding,
+ );
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
+ ..add(DiagnosticsProperty('titleTextStyle', titleTextStyle))
+ ..add(DiagnosticsProperty('bodyTextStyle', bodyTextStyle))
..add(DiagnosticsProperty('padding', padding))
- ..add(DiagnosticsProperty('title', title))
- ..add(DiagnosticsProperty('subtitle', body))
..add(DoubleProperty('actionPadding', actionPadding));
}
}
diff --git a/forui/lib/src/widgets/header/header.dart b/forui/lib/src/widgets/header/header.dart
index b1960784f..16346309d 100644
--- a/forui/lib/src/widgets/header/header.dart
+++ b/forui/lib/src/widgets/header/header.dart
@@ -1,41 +1,61 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
+
import 'package:forui/forui.dart';
import 'package:forui/src/foundation/tappable.dart';
part 'header_action.dart';
-/// A header widget.
+/// A header.
+///
+/// A header contains the page's title and navigation actions. It is typically used on pages at the root of the
+/// navigation stack.
///
-/// Typically used on pages at the root of the navigation stack.
-final class FHeader extends StatelessWidget {
- /// The title displayed on the left side of the [FHeader].
+/// See:
+/// * https://forui.dev/docs/header for working examples.
+/// * [FHeaderStyle] for customizing a header's appearance.
+class FHeader extends StatelessWidget {
+ /// The header's style. Defaults to [FThemeData.headerStyle].
+ final FHeaderStyle? style;
+
+ /// The title, aligned to the left.
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError]:
+ /// * if [title] and [rawTitle] are both not null
+ /// * if [title] and [rawTitle] are both null
final String? title;
- /// The title displayed on the left side of the [FHeader].
+ /// The title, aligned to the left.
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError]:
+ /// * if [title] and [rawTitle] are both not null
+ /// * if [title] and [rawTitle] are both null
final Widget? rawTitle;
- /// The actions displayed on the right side of the [FHeader].
+ /// The actions, aligned to the right. Defaults to an empty list.
final List actions;
- /// The style.
- final FHeaderStyle? style;
-
/// Creates a [FHeader].
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError]:
+ /// * if [title] and [rawTitle] are both not null
+ /// * if [title] and [rawTitle] are both null
const FHeader({
+ this.style,
this.title,
this.rawTitle,
this.actions = const [],
- this.style,
super.key,
- }):
- assert((title != null) ^ (rawTitle != null), 'title or rawTitle must be provided, but not both.');
+ }) : assert((title != null) ^ (rawTitle != null), 'title or rawTitle must be provided, but not both.');
@override
Widget build(BuildContext context) {
final style = this.style ?? context.theme.headerStyle;
- final typography = context.theme.typography;
final title = switch ((this.title, rawTitle)) {
(final String title, _) => Text(title),
@@ -51,7 +71,7 @@ final class FHeader extends StatelessWidget {
overflow: TextOverflow.fade,
maxLines: 1,
softWrap: false,
- style: style.title.scale(typography),
+ style: style.titleTextStyle,
child: title,
),
),
@@ -64,37 +84,62 @@ final class FHeader extends StatelessWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
+ ..add(DiagnosticsProperty('style', style))
..add(StringProperty('title', title))
- ..add(IterableProperty('actions', actions))
- ..add(DiagnosticsProperty('style', style));
+ ..add(IterableProperty('actions', actions));
}
}
/// [FHeader]'s style.
final class FHeaderStyle with Diagnosticable {
- /// The title's style.
- final TextStyle title;
+ /// The title's [TextStyle].
+ final TextStyle titleTextStyle;
/// The [FHeaderAction]'s style.
final FHeaderActionStyle action;
/// Creates a [FHeaderStyle].
- FHeaderStyle({required this.title, required this.action});
+ FHeaderStyle({required this.titleTextStyle, required this.action});
/// Creates a [FHeaderStyle] that inherits its properties from the given [FColorScheme] and [FTypography].
FHeaderStyle.inherit({required FColorScheme colorScheme, required FTypography typography})
- : title = TextStyle(
- fontSize: typography.xl3,
- fontWeight: FontWeight.w700,
+ : titleTextStyle = typography.xl3.copyWith(
color: colorScheme.foreground,
+ fontWeight: FontWeight.w700,
+ height: 1,
),
action = FHeaderActionStyle.inherit(colorScheme: colorScheme);
+ /// Returns a copy of this [FHeaderStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FHeaderStyle(
+ /// titleTextStyle: ...,
+ /// action: ...,
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// action: ...,
+ /// );
+ ///
+ /// print(style.titleTextStyle == copy.titleTextStyle); // true
+ /// print(style.action == copy.action); // false
+ /// ```
+ @useResult
+ FHeaderStyle copyWith({
+ TextStyle? titleTextStyle,
+ FHeaderActionStyle? action,
+ }) =>
+ FHeaderStyle(
+ titleTextStyle: titleTextStyle ?? this.titleTextStyle,
+ action: action ?? this.action,
+ );
+
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(DiagnosticsProperty('title', title))
- ..add(DiagnosticsProperty('actionStyle', action));
+ ..add(DiagnosticsProperty('titleTextStyle', titleTextStyle))
+ ..add(DiagnosticsProperty('action', action));
}
}
diff --git a/forui/lib/src/widgets/header/header_action.dart b/forui/lib/src/widgets/header/header_action.dart
index abe95a50b..68dd9c66b 100644
--- a/forui/lib/src/widgets/header/header_action.dart
+++ b/forui/lib/src/widgets/header/header_action.dart
@@ -1,34 +1,49 @@
part of 'header.dart';
-/// Represents a [FHeader]'s action.
+/// A [FHeader] action.
+///
+/// If the [onPress] and [onLongPress] callbacks are null, then this action will be disabled, it will not react to touch.
class FHeaderAction extends StatelessWidget {
- /// The icon;
+ /// The style.
+ final FHeaderActionStyle? style;
+
+ /// The icon.
final SvgAsset icon;
- /// The callback.
+ /// A callback for when the button is pressed.
///
- /// If null, the action is disabled.
+ /// The action will be disabled if both [onPress] and [onLongPress] are null.
final VoidCallback? onPress;
- /// The style.
- final FHeaderActionStyle? style;
+ /// A callback for when the button is long pressed.
+ ///
+ /// The action will be disabled if both [onPress] and [onLongPress] are null.
+ final VoidCallback? onLongPress;
- /// Creates a [FHeaderAction].
- const FHeaderAction({required this.icon, required this.onPress, this.style, super.key});
+ /// Creates a [FHeaderAction] from the given SVG [icon].
+ const FHeaderAction({
+ required this.icon,
+ required this.onPress,
+ this.onLongPress,
+ this.style,
+ super.key,
+ });
@override
Widget build(BuildContext context) {
final style = this.style ?? context.theme.headerStyle.action;
+ final enabled = onPress != null || onLongPress != null;
return Padding(
padding: style.padding,
child: MouseRegion(
- cursor: onPress == null ? MouseCursor.defer : SystemMouseCursors.click,
+ cursor: enabled ? SystemMouseCursors.click : MouseCursor.defer,
child: FTappable(
onTap: onPress,
+ onLongPress: onLongPress,
child: icon(
- height: style.iconSize,
- colorFilter: ColorFilter.mode(onPress == null ? style.disabledIcon : style.enabledIcon, BlendMode.srcIn),
+ height: style.size,
+ colorFilter: ColorFilter.mode(onPress == null ? style.disabledColor : style.enabledColor, BlendMode.srcIn),
),
),
),
@@ -39,48 +54,77 @@ class FHeaderAction extends StatelessWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
+ ..add(DiagnosticsProperty('style', style))
..add(DiagnosticsProperty('icon', icon))
..add(DiagnosticsProperty('onPress', onPress))
- ..add(DiagnosticsProperty('style', style));
+ ..add(DiagnosticsProperty('onLongPress', onLongPress));
}
}
/// [FHeaderAction]'s style.
class FHeaderActionStyle with Diagnosticable {
- /// The icon's size. Defaults to 30.
- final double iconSize;
+ /// The icon's color when this action is enabled.
+ final Color enabledColor;
- /// The icon's color when this button is enabled. Defaults to [FColorScheme.foreground].
- final Color enabledIcon;
+ /// The icon's color when this action is disabled.
+ final Color disabledColor;
- /// The icon's color when this button is disabled. Defaults to a slightly translucent [FColorScheme.foreground].
- final Color disabledIcon;
+ /// The icon's size. Defaults to 30.
+ final double size;
/// The padding. Defaults to `EdgeInsets.only(left: 10)`.
final EdgeInsets padding;
/// Creates a [FHeaderActionStyle].
FHeaderActionStyle({
- required this.iconSize,
- required this.enabledIcon,
- required this.disabledIcon,
- required this.padding,
+ required this.enabledColor,
+ required this.disabledColor,
+ this.size = 30,
+ this.padding = const EdgeInsets.only(left: 10),
});
/// Creates a [FHeaderActionStyle] that inherits its properties from the given [FColorScheme].
FHeaderActionStyle.inherit({required FColorScheme colorScheme})
- : iconSize = 30,
- padding = const EdgeInsets.only(left: 10),
- enabledIcon = colorScheme.foreground,
- disabledIcon = colorScheme.foreground.withOpacity(0.5);
+ : enabledColor = colorScheme.foreground,
+ disabledColor = colorScheme.foreground.withOpacity(0.5),
+ size = 30,
+ padding = const EdgeInsets.only(left: 10);
+
+ /// Returns a copy of this [FHeaderActionStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FHeaderActionStyle(
+ /// enabledColor: Colors.black,
+ /// disabledColor: Colors.white,
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// disabledColor: Colors.blue,
+ /// );
+ ///
+ /// print(copy.enabledColor); // black
+ /// print(copy.disabledColor); // blue
+ /// ```
+ @useResult FHeaderActionStyle copyWith({
+ Color? enabledColor,
+ Color? disabledColor,
+ double? size,
+ EdgeInsets? padding,
+ }) =>
+ FHeaderActionStyle(
+ enabledColor: enabledColor ?? this.enabledColor,
+ disabledColor: disabledColor ?? this.disabledColor,
+ size: size ?? this.size,
+ padding: padding ?? this.padding,
+ );
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(DoubleProperty('iconSize', iconSize, defaultValue: 30))
- ..add(ColorProperty('enabledIcon', enabledIcon))
- ..add(ColorProperty('disabledIcon', disabledIcon))
+ ..add(ColorProperty('enabledColor', enabledColor))
+ ..add(ColorProperty('disabledColor', disabledColor))
+ ..add(DoubleProperty('size', size, defaultValue: 30))
..add(DiagnosticsProperty('padding', padding, defaultValue: const EdgeInsets.only(left: 10)));
}
}
diff --git a/forui/lib/src/widgets/separator.dart b/forui/lib/src/widgets/separator.dart
index 6e4daae45..962dad1ae 100644
--- a/forui/lib/src/widgets/separator.dart
+++ b/forui/lib/src/widgets/separator.dart
@@ -1,12 +1,18 @@
import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
+import 'package:meta/meta.dart';
+
import 'package:forui/forui.dart';
-/// A separator that visually separates content.
+/// A separator. Separators visually separate content.
+///
+/// See:
+/// * https://forui.dev/docs/separator for working examples.
+/// * [FBadgeCustomStyle] for customizing a separator's appearance.
final class FSeparator extends StatelessWidget {
-
- /// The style. Defaults to the appropriate style in [FThemeData.separatorStyles] if null.
+ /// The separator's style. Defaults to the appropriate style in [FThemeData.separatorStyles].
final FSeparatorStyle? style;
/// True if this separator is vertical. Defaults to false (horizontal).
@@ -17,24 +23,14 @@ final class FSeparator extends StatelessWidget {
@override
Widget build(BuildContext context) {
- final FSeparatorStyle(:padding, :width, :color) = style ?? (vertical ? context.theme.separatorStyles.vertical : context.theme.separatorStyles.horizontal);
- return Padding(
- padding: padding,
- child: vertical ?
- SizedBox(
- width: width,
- height: double.infinity,
- child: ColoredBox(
- color: color,
- ),
- ) :
- SizedBox(
- width: double.infinity,
- height: width,
- child: ColoredBox(
- color: color,
- ),
- ),
+ final style = this.style ?? (vertical ? context.theme.separatorStyles.vertical : context.theme.separatorStyles.horizontal);
+ final (height, width) = vertical ? (null, style.width) : (style.width, null);
+
+ return Container(
+ margin: style.padding,
+ color: style.color,
+ height: height,
+ width: width,
);
}
@@ -42,25 +38,23 @@ final class FSeparator extends StatelessWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(FlagProperty('vertical', value: vertical, defaultValue: false))
+ ..add(FlagProperty('vertical', value: vertical, defaultValue: false, ifTrue: 'vertical'))
..add(DiagnosticsProperty('style', style));
}
-
}
/// The [FSeparator] styles.
final class FSeparatorStyles with Diagnosticable {
-
- /// The horizontal separator style.
+ /// The horizontal separator's style.
final FSeparatorStyle horizontal;
- /// The vertical separator style.
+ /// The vertical separator's style.
final FSeparatorStyle vertical;
/// Creates a [FSeparatorStyles].
FSeparatorStyles({required this.horizontal, required this.vertical});
- /// Creates a [FSeparatorStyles] that inherits its properties from [colorScheme].
+ /// Creates a [FSeparatorStyles] that inherits its properties from [colorScheme] and [style].
FSeparatorStyles.inherit({required FColorScheme colorScheme, required FStyle style}):
horizontal = FSeparatorStyle.inherit(
colorScheme: colorScheme,
@@ -73,7 +67,19 @@ final class FSeparatorStyles with Diagnosticable {
padding: FSeparatorStyle.defaultPadding.vertical
);
- /// Creates a copy of this [FSeparatorStyles] with the given properties replaced.
+ /// Returns a copy of this [FSeparatorStyles] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FSeparatorStyles(
+ /// horizontal: ...,
+ /// vertical: ...,
+ /// );
+ ///
+ /// final copy = style.copyWith(vertical: ...);
+ ///
+ /// print(style.horizontal == copy.horizontal); // true
+ /// print(style.vertical == copy.vertical); // false
+ /// ```
FSeparatorStyles copyWith({FSeparatorStyle? horizontal, FSeparatorStyle? vertical}) => FSeparatorStyles(
horizontal: horizontal ?? this.horizontal,
vertical: vertical ?? this.vertical,
@@ -102,14 +108,13 @@ final class FSeparatorStyles with Diagnosticable {
/// [FSeparator]'s style.
final class FSeparatorStyle with Diagnosticable {
-
/// The default padding for horizontal and vertical separators.
static const defaultPadding = (
horizontal: EdgeInsets.symmetric(vertical: 20),
vertical: EdgeInsets.symmetric(horizontal: 20),
);
- /// The color of the separating line. Defaults to [FColorScheme.secondary].
+ /// The color of the separating line..
final Color color;
/// The padding surrounding the separating line. Defaults to the appropriate padding in [defaultPadding].
@@ -118,7 +123,7 @@ final class FSeparatorStyle with Diagnosticable {
/// The width of the separating line. Defaults to 1.
///
/// ## Contract:
- /// Throws an [AssertionError] if:
+ /// Throws [AssertionError] if:
/// * `width` <= 0.0
/// * `width` is Nan
final double width;
@@ -127,12 +132,25 @@ final class FSeparatorStyle with Diagnosticable {
FSeparatorStyle({required this.color, required this.padding, this.width = 1}):
assert(0 < width, 'The width is $width, but it should be in the range "0 < width".');
- /// Creates a [FCardContentStyle] that inherits its properties from [colorScheme].
+ /// Creates a [FCardContentStyle] that inherits its properties from [colorScheme], [style], and [padding].
FSeparatorStyle.inherit({required FColorScheme colorScheme, required FStyle style, required EdgeInsetsGeometry padding}):
this(color: colorScheme.secondary, padding: padding, width: style.borderWidth);
- /// Creates a copy of this [FSeparatorStyle] with the given properties replaced.
- FSeparatorStyle copyWith({Color? color, EdgeInsetsGeometry? padding, double? width}) => FSeparatorStyle(
+ /// Returns a copy of this [FSeparatorStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FSeparatorStyle(
+ /// color: Colors.black,
+ /// width: 1,
+ /// // Other arguments omitted for brevity
+ /// );
+ ///
+ /// final copy = style.copyWith(width: 2);
+ ///
+ /// print(copy.color); // black
+ /// print(copy.width); // 2
+ /// ```
+ @useResult FSeparatorStyle copyWith({Color? color, EdgeInsetsGeometry? padding, double? width}) => FSeparatorStyle(
color: color ?? this.color,
padding: padding ?? this.padding,
width: width ?? this.width,
@@ -158,5 +176,4 @@ final class FSeparatorStyle with Diagnosticable {
@override
int get hashCode => color.hashCode ^ padding.hashCode ^ width.hashCode;
-
}
diff --git a/forui/lib/src/widgets/switch.dart b/forui/lib/src/widgets/switch.dart
index 12740396a..851218efe 100644
--- a/forui/lib/src/widgets/switch.dart
+++ b/forui/lib/src/widgets/switch.dart
@@ -2,12 +2,19 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
+import 'package:meta/meta.dart';
+
import 'package:forui/forui.dart';
/// A control that allows the user to toggle between checked and unchecked.
+///
+/// Typically used to toggle the on/off state of a single setting.
+///
+/// See:
+/// * https://forui.dev/docs/switch for working examples.
+/// * [FSwitchStyle] for customizing a switch's appearance.
class FSwitch extends StatelessWidget {
-
- /// The style. Defaults to the appropriate style in [FThemeData.switchStyle] if null.
+ /// The style. Defaults to [FThemeData.switchStyle].
final FSwitchStyle? style;
/// True if this switch is checked, and false if unchecked.
@@ -39,10 +46,10 @@ class FSwitch extends StatelessWidget {
/// True if this widget will be selected as the initial focus when no other node in its scope is currently focused.
///
+ /// Defaults to false.
+ ///
/// Ideally, there is only one widget with autofocus set in each FocusScope. If there is more than one widget with
/// autofocus set, then the first one added to the tree will get focus.
- ///
- /// Defaults to false.
final bool autofocus;
/// An optional focus node to use as the focus node for this widget.
@@ -93,10 +100,10 @@ class FSwitch extends StatelessWidget {
return CupertinoSwitch(
value: value,
onChanged: onChanged,
- activeColor: style.checked,
- trackColor: style.unchecked,
- thumbColor: style.thumb,
- focusColor: style.focus,
+ activeColor: style.checkedColor,
+ trackColor: style.uncheckedColor,
+ thumbColor: style.thumbColor,
+ focusColor: style.focusColor,
autofocus: autofocus,
focusNode: focusNode,
onFocusChange: onFocusChange,
@@ -110,44 +117,43 @@ class FSwitch extends StatelessWidget {
properties
..add(DiagnosticsProperty('style', style))
..add(FlagProperty('value', value: value))
- ..add(FlagProperty('autofocus', value: autofocus, defaultValue: false))
+ ..add(FlagProperty('autofocus', value: autofocus, defaultValue: false, ifTrue: 'autofocus'))
..add(EnumProperty('dragStartBehavior', dragStartBehavior, defaultValue: DragStartBehavior.start))
- ..add(DiagnosticsProperty('onChanged', onChanged, defaultValue: null))
- ..add(DiagnosticsProperty('focusNode', focusNode, defaultValue: null))
- ..add(DiagnosticsProperty('onFocusChange', onFocusChange, defaultValue: null));
+ ..add(DiagnosticsProperty('onChanged', onChanged))
+ ..add(DiagnosticsProperty('focusNode', focusNode))
+ ..add(DiagnosticsProperty('onFocusChange', onFocusChange));
}
}
-/// The style of a [FSwitch].
+/// [FSwitch]'s style.
final class FSwitchStyle with Diagnosticable {
+ /// The track's color when checked.
+ final Color checkedColor;
- /// The track's color when checked. Defaults to [FColorScheme.primary].
- final Color checked;
+ /// The track's color when unchecked.
+ final Color uncheckedColor;
- /// The track's color when unchecked. Defaults to [FColorScheme.border].
- final Color unchecked;
+ /// The thumb's color.
+ final Color thumbColor;
- /// The thumb's color. Defaults to [FColorScheme.background].
- final Color thumb;
-
- /// This switch's color when focused. Defaults to a slightly transparent [checked] color.
- final Color focus;
+ /// This switch's color when focused.
+ final Color focusColor;
/// Creates a [FSwitchStyle].
const FSwitchStyle({
- required this.checked,
- required this.unchecked,
- required this.thumb,
- required this.focus,
+ required this.checkedColor,
+ required this.uncheckedColor,
+ required this.thumbColor,
+ required this.focusColor,
});
/// Creates a [FSwitchStyle] that inherits its properties from [colorScheme].
FSwitchStyle.inherit({required FColorScheme colorScheme})
- : checked = colorScheme.primary,
- unchecked = colorScheme.border,
- thumb = colorScheme.background,
- focus = HSLColor.fromColor(colorScheme.primary.withOpacity(0.80))
+ : checkedColor = colorScheme.primary,
+ uncheckedColor = colorScheme.border,
+ thumbColor = colorScheme.background,
+ focusColor = HSLColor.fromColor(colorScheme.primary.withOpacity(0.80))
.withLightness(0.69)
.withSaturation(0.835)
.toColor();
@@ -156,23 +162,48 @@ final class FSwitchStyle with Diagnosticable {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(ColorProperty('checked', checked))
- ..add(ColorProperty('unchecked', unchecked))
- ..add(ColorProperty('thumb', thumb))
- ..add(ColorProperty('focus', focus));
+ ..add(ColorProperty('checkedColor', checkedColor))
+ ..add(ColorProperty('uncheckedColor', uncheckedColor))
+ ..add(ColorProperty('thumbColor', thumbColor))
+ ..add(ColorProperty('focusColor', focusColor));
}
+ /// Returns a copy of this [FSwitchStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FSwitch(
+ /// checkedColor: Colors.black,
+ /// uncheckedColor: Colors.white,
+ /// // Other arguments omitted for brevity
+ /// );
+ ///
+ /// final copy = style.copyWith(uncheckedColor: Colors.blue);
+ ///
+ /// print(copy.checkedColor); // black
+ /// print(copy.uncheckedColor); // blue
+ /// ```
+ @useResult FSwitchStyle copyWith({
+ Color? checkedColor,
+ Color? uncheckedColor,
+ Color? thumbColor,
+ Color? focusColor,
+ }) => FSwitchStyle(
+ checkedColor: checkedColor ?? this.checkedColor,
+ uncheckedColor: uncheckedColor ?? this.uncheckedColor,
+ thumbColor: thumbColor ?? this.thumbColor,
+ focusColor: focusColor ?? this.focusColor,
+ );
+
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is FSwitchStyle &&
runtimeType == other.runtimeType &&
- checked == other.checked &&
- unchecked == other.unchecked &&
- thumb == other.thumb &&
- focus == other.focus;
+ checkedColor == other.checkedColor &&
+ uncheckedColor == other.uncheckedColor &&
+ thumbColor == other.thumbColor &&
+ focusColor == other.focusColor;
@override
- int get hashCode => checked.hashCode ^ unchecked.hashCode ^ thumb.hashCode ^ focus.hashCode;
-
+ int get hashCode => checkedColor.hashCode ^ uncheckedColor.hashCode ^ thumbColor.hashCode ^ focusColor.hashCode;
}
diff --git a/forui/lib/src/widgets/text_field/text_field.dart b/forui/lib/src/widgets/text_field/text_field.dart
index 11e26a31d..c6f10128a 100644
--- a/forui/lib/src/widgets/text_field/text_field.dart
+++ b/forui/lib/src/widgets/text_field/text_field.dart
@@ -5,25 +5,41 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
+import 'package:meta/meta.dart';
import 'package:forui/forui.dart';
part 'text_field_style.dart';
/// A text field.
+///
+/// It lets the user enter text, either with hardware keyboard or with an onscreen keyboard.
+///
+/// See:
+/// * https://forui.dev/docs/text-field for working examples.
+/// * [FTextFieldStyle] for customizing a text field's appearance.
+/// * [TextField] for more details about working with a text field.
final class FTextField extends StatelessWidget {
static Widget _defaultContextMenuBuilder(
BuildContext context,
EditableTextState editableTextState,
) => AdaptiveTextSelectionToolbar.editableText(editableTextState: editableTextState);
- /// The style.
+ /// The text field's style. Defaults to [FThemeData.textFieldStyle].
final FTextFieldStyle? style;
- /// The label.
+ /// The label above a text field.
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * both [label] and [rawLabel] are not null
final String? label;
- /// The raw label.
+ /// The raw label above a text field.
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * both [label] and [rawLabel] are not null
final Widget? rawLabel;
/// The text to display when the text field is empty.
@@ -463,6 +479,12 @@ final class FTextField extends StatelessWidget {
final Widget? suffixIcon;
/// Creates a [FTextField].
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * both [label] and [rawLabel] are not null
+ /// * both [help] and [rawHelp] are not null
+ /// * both [error] and [rawError] are not null
const FTextField({
this.style,
this.label,
@@ -590,6 +612,12 @@ final class FTextField extends StatelessWidget {
///
/// [autofillHints] defaults to [AutofillHints.password]. It should be overridden with [AutofillHints.newPassword]
/// when handling the creation of new passwords.
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * both [label] and [rawLabel] are not null
+ /// * both [help] and [rawHelp] are not null
+ /// * both [error] and [rawError] are not null
const FTextField.password({
this.style,
this.label,
@@ -652,6 +680,14 @@ final class FTextField extends StatelessWidget {
assert(error == null || rawError == null, 'Cannot provide both an error and a rawError.');
/// Creates a [FTextField] configured for multiline inputs.
+ ///
+ /// The text field's height can be configured by adjusting [minLines].
+ ///
+ /// ## Contract:
+ /// Throws [AssertionError] if:
+ /// * both [label] and [rawLabel] are not null
+ /// * both [help] and [rawHelp] are not null
+ /// * both [error] and [rawError] are not null
const FTextField.multiline({
this.style,
this.label,
@@ -739,7 +775,7 @@ final class FTextField extends StatelessWidget {
Padding(
padding: const EdgeInsets.only(top: 4, bottom: 7),
child: DefaultTextStyle.merge(
- style: stateStyle.label.scale(typography),
+ style: stateStyle.labelTextStyle,
child: label,
),
),
@@ -750,12 +786,12 @@ final class FTextField extends StatelessWidget {
// for overriding selectionHandleColor.
data: Theme.of(context).copyWith(
textSelectionTheme: TextSelectionThemeData(
- cursorColor: style.cursor,
- selectionColor: style.cursor.withOpacity(0.4),
- selectionHandleColor: style.cursor,
+ cursorColor: style.cursorColor,
+ selectionColor: style.cursorColor.withOpacity(0.4),
+ selectionHandleColor: style.cursorColor,
),
cupertinoOverrideTheme: CupertinoThemeData(
- primaryColor: style.cursor,
+ primaryColor: style.cursorColor,
),
),
child: _textField(context, typography, style, stateStyle),
@@ -786,12 +822,12 @@ final class FTextField extends StatelessWidget {
) {
final rawError = this.rawError == null ? this.rawError : DefaultTextStyle.merge(
- style: current.footer.scale(typography),
+ style: current.footerTextStyle,
child: this.rawError!,
);
final rawHelp = this.rawHelp == null ? this.rawHelp : DefaultTextStyle.merge(
- style: current.footer.scale(typography),
+ style: current.footerTextStyle,
child: this.rawHelp!,
);
@@ -799,22 +835,22 @@ final class FTextField extends StatelessWidget {
controller: controller,
focusNode: focusNode,
undoController: undoController,
- cursorErrorColor: style.cursor,
+ cursorErrorColor: style.cursorColor,
decoration: InputDecoration(
suffixIcon: suffixIcon,
// See https://stackoverflow.com/questions/70771410/flutter-how-can-i-remove-the-content-padding-for-error-in-textformfield
prefix: Padding(padding: EdgeInsets.only(left: style.contentPadding.left)),
contentPadding: style.contentPadding.copyWith(left: 0),
hintText: hint,
- hintStyle: current.hint.scale(typography),
+ hintStyle: current.hintTextStyle,
hintMaxLines: hintMaxLines,
helper: rawHelp,
helperText: help,
- helperStyle: current.footer.scale(typography),
+ helperStyle: current.footerTextStyle,
helperMaxLines: helpMaxLines,
error: rawError,
errorText: error,
- errorStyle: current.footer.scale(typography),
+ errorStyle: current.footerTextStyle,
errorMaxLines: errorMaxLines,
disabledBorder: OutlineInputBorder(
borderSide: BorderSide(
@@ -855,7 +891,7 @@ final class FTextField extends StatelessWidget {
keyboardType: keyboardType,
textInputAction: textInputAction,
textCapitalization: textCapitalization,
- style: current.content.scale(typography),
+ style: current.contentTextStyle,
textAlign: textAlign,
textAlignVertical: textAlignVertical,
textDirection: textDirection,
diff --git a/forui/lib/src/widgets/text_field/text_field_style.dart b/forui/lib/src/widgets/text_field/text_field_style.dart
index d2030592a..1c7b97a8f 100644
--- a/forui/lib/src/widgets/text_field/text_field_style.dart
+++ b/forui/lib/src/widgets/text_field/text_field_style.dart
@@ -1,6 +1,6 @@
part of 'text_field.dart';
-/// A [FTextFieldStyle]'s style.
+/// [FTextFieldStyle]'s style.
final class FTextFieldStyle with Diagnosticable {
/// The appearance of the keyboard. Defaults to [FColorScheme.brightness].
///
@@ -10,15 +10,16 @@ final class FTextFieldStyle with Diagnosticable {
/// The color of the cursor. Defaults to [CupertinoColors.activeBlue].
///
/// The cursor indicates the current location of text insertion point in the field.
- final Color cursor;
+ final Color cursorColor;
- /// The padding surrounding this text field's content. Defaults to
- /// `const EdgeInsets.symmetric(horizontal: 15, vertical: 6)`.
+ /// The padding surrounding this text field's content.
+ ///
+ /// Defaults to `const EdgeInsets.symmetric(horizontal: 15, vertical: 5)`.
final EdgeInsets contentPadding;
/// Configures padding to edges surrounding a [Scrollable] when this text field scrolls into view.
///
- /// Defaults to `EdgeInsets.all(20.0)`.
+ /// Defaults to `EdgeInsets.all(20)`.
///
/// When this widget receives focus and is not completely visible (for example scrolled partially off the screen or
/// overlapped by the keyboard) then it will attempt to make itself visible by scrolling a surrounding [Scrollable],
@@ -41,9 +42,9 @@ final class FTextFieldStyle with Diagnosticable {
required this.enabled,
required this.disabled,
required this.error,
- this.cursor = CupertinoColors.activeBlue,
+ this.cursorColor = CupertinoColors.activeBlue,
this.contentPadding = const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
- this.scrollPadding = const EdgeInsets.all(20.0),
+ this.scrollPadding = const EdgeInsets.all(20),
});
/// Creates a [FTextFieldStyle] that inherits its properties.
@@ -53,7 +54,7 @@ final class FTextFieldStyle with Diagnosticable {
required FStyle style,
}):
keyboardAppearance = colorScheme.brightness,
- cursor = CupertinoColors.activeBlue,
+ cursorColor = CupertinoColors.activeBlue,
contentPadding = const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
scrollPadding = const EdgeInsets.all(20.0),
enabled = FTextFieldStateStyle.inherit(
@@ -87,12 +88,46 @@ final class FTextFieldStyle with Diagnosticable {
style: style,
);
+ /// Returns a copy of this [FTextFieldStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FTextFieldStyle(
+ /// enabled: ...,
+ /// disabled: ...,
+ /// // Other arguments omitted for brevity
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// disabled: ...,
+ /// );
+ ///
+ /// print(style.enabled == copy.enabled); // true
+ /// print(style.disabled == copy.disabled); // false
+ /// ```
+ @useResult FTextFieldStyle copyWith({
+ Brightness? keyboardAppearance,
+ Color? cursorColor,
+ EdgeInsets? contentPadding,
+ EdgeInsets? scrollPadding,
+ FTextFieldStateStyle? enabled,
+ FTextFieldStateStyle? disabled,
+ FTextFieldStateStyle? error,
+ }) => FTextFieldStyle(
+ keyboardAppearance: keyboardAppearance ?? this.keyboardAppearance,
+ cursorColor: cursorColor ?? this.cursorColor,
+ contentPadding: contentPadding ?? this.contentPadding,
+ scrollPadding: scrollPadding ?? this.scrollPadding,
+ enabled: enabled ?? this.enabled,
+ disabled: disabled ?? this.disabled,
+ error: error ?? this.error,
+ );
+
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(EnumProperty('keyboardAppearance', keyboardAppearance))
- ..add(ColorProperty('cursor', cursor, defaultValue: CupertinoColors.activeBlue))
+ ..add(ColorProperty('cursorColor', cursorColor, defaultValue: CupertinoColors.activeBlue))
..add(DiagnosticsProperty('contentPadding', contentPadding))
..add(DiagnosticsProperty('scrollPadding', scrollPadding))
..add(DiagnosticsProperty('enabledBorder', enabled))
@@ -106,7 +141,7 @@ final class FTextFieldStyle with Diagnosticable {
other is FTextFieldStyle &&
runtimeType == other.runtimeType &&
keyboardAppearance == other.keyboardAppearance &&
- cursor == other.cursor &&
+ cursorColor == other.cursorColor &&
contentPadding == other.contentPadding &&
scrollPadding == other.scrollPadding &&
enabled == other.enabled &&
@@ -116,7 +151,7 @@ final class FTextFieldStyle with Diagnosticable {
@override
int get hashCode =>
keyboardAppearance.hashCode ^
- cursor.hashCode ^
+ cursorColor.hashCode ^
contentPadding.hashCode ^
scrollPadding.hashCode ^
enabled.hashCode ^
@@ -124,19 +159,19 @@ final class FTextFieldStyle with Diagnosticable {
error.hashCode;
}
-/// A [FTextFieldStateStyle]'s style.
+/// A [FTextField] state's style.
final class FTextFieldStateStyle with Diagnosticable {
/// The label's [TextStyle].
- final TextStyle label;
+ final TextStyle labelTextStyle;
/// The content's [TextStyle].
- final TextStyle content;
+ final TextStyle contentTextStyle;
/// The hint's [TextStyle].
- final TextStyle hint;
+ final TextStyle hintTextStyle;
/// The help/error's [TextStyle].
- final TextStyle footer;
+ final TextStyle footerTextStyle;
/// The border's color when focused.
final FTextFieldBorderStyle focused;
@@ -146,10 +181,10 @@ final class FTextFieldStateStyle with Diagnosticable {
/// Creates a [FTextFieldStateStyle].
FTextFieldStateStyle({
- required this.label,
- required this.content,
- required this.hint,
- required this.footer,
+ required this.labelTextStyle,
+ required this.contentTextStyle,
+ required this.hintTextStyle,
+ required this.footerTextStyle,
required this.focused,
required this.unfocused,
});
@@ -165,37 +200,65 @@ final class FTextFieldStateStyle with Diagnosticable {
required FTypography typography,
required FStyle style,
}):
- label = TextStyle(
+ labelTextStyle = typography.sm.copyWith(
color: labelColor,
- fontSize: typography.sm,
fontWeight: FontWeight.w600,
),
- content = TextStyle(
+ contentTextStyle = typography.sm.copyWith(
fontFamily: typography.defaultFontFamily,
- fontSize: typography.sm,
color: contentColor,
),
- hint = TextStyle(
+ hintTextStyle = typography.sm.copyWith(
fontFamily: typography.defaultFontFamily,
- fontSize: typography.sm,
color: hintColor,
),
- footer = TextStyle(
+ footerTextStyle = typography.sm.copyWith(
fontFamily: typography.defaultFontFamily,
- fontSize: typography.sm,
color: footerColor,
),
focused = FTextFieldBorderStyle.inherit(color: focusedBorderColor, style: style),
unfocused = FTextFieldBorderStyle.inherit(color: unfocusedBorderColor, style: style);
+ /// Returns a copy of this [FTextFieldStateStyle] with the given properties replaced.
+ ///
+ /// ```dart
+ /// final style = FTextFieldStateStyle(
+ /// labelTextStyle: ...,
+ /// contentTextStyle: ...,
+ /// // Other arguments omitted for brevity
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// contentTextStyle: ...,
+ /// );
+ ///
+ /// print(style.labelTextStyle == copy.labelTextStyle); // true
+ /// print(style.contentTextStyle == copy.contentTextStyle); // false
+ /// ```
+ @useResult FTextFieldStateStyle copyWith({
+ TextStyle? labelTextStyle,
+ TextStyle? contentTextStyle,
+ TextStyle? hintTextStyle,
+ TextStyle? footerTextStyle,
+ FTextFieldBorderStyle? focused,
+ FTextFieldBorderStyle? unfocused,
+ }) => FTextFieldStateStyle(
+ labelTextStyle: labelTextStyle ?? this.labelTextStyle,
+ contentTextStyle: contentTextStyle ?? this.contentTextStyle,
+ hintTextStyle: hintTextStyle ?? this.hintTextStyle,
+ footerTextStyle: footerTextStyle ?? this.footerTextStyle,
+ focused: focused ?? this.focused,
+ unfocused: unfocused ?? this.unfocused,
+ );
+
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(DiagnosticsProperty('label', label))
- ..add(DiagnosticsProperty('content', content))
- ..add(DiagnosticsProperty('hint', hint))
- ..add(DiagnosticsProperty('footer', footer))
+ ..add(DiagnosticsProperty('labelTextStyle', labelTextStyle))
+ ..add(DiagnosticsProperty('contentTextStyle', contentTextStyle))
+ ..add(DiagnosticsProperty('hintTextStyle', hintTextStyle))
+ ..add(DiagnosticsProperty('footerTextStyle', footerTextStyle))
..add(DiagnosticsProperty('focused', focused))
..add(DiagnosticsProperty('unfocused', unfocused));
}
@@ -205,22 +268,22 @@ final class FTextFieldStateStyle with Diagnosticable {
identical(this, other) ||
other is FTextFieldStateStyle &&
runtimeType == other.runtimeType &&
- label == other.label &&
- content == other.content &&
- hint == other.hint &&
+ labelTextStyle == other.labelTextStyle &&
+ contentTextStyle == other.contentTextStyle &&
+ hintTextStyle == other.hintTextStyle &&
focused == other.focused &&
unfocused == other.unfocused;
@override
int get hashCode =>
- label.hashCode ^
- content.hashCode ^
- hint.hashCode ^
+ labelTextStyle.hashCode ^
+ contentTextStyle.hashCode ^
+ hintTextStyle.hashCode ^
focused.hashCode ^
unfocused.hashCode;
}
-/// A [FTextFieldBorderStyle]'s style.
+/// A [FTextField] border's style.
final class FTextFieldBorderStyle with Diagnosticable {
/// The border's color.
final Color color;
@@ -238,7 +301,7 @@ final class FTextFieldBorderStyle with Diagnosticable {
required this.radius,
});
- /// Creates a [FTextFieldBorderStyle] that inherits its properties.
+ /// Creates a [FTextFieldBorderStyle] that inherits its properties from [style].
FTextFieldBorderStyle.inherit({
required this.color,
required FStyle style,
@@ -246,8 +309,22 @@ final class FTextFieldBorderStyle with Diagnosticable {
width = style.borderWidth,
radius = style.borderRadius;
- /// Creates a copy of this border style but with the given fields replaced with the new values.
- FTextFieldBorderStyle copyWith({
+ /// Returns a copy of this border style but with the given fields replaced with the new values.
+ ///
+ /// ```dart
+ /// final style = FTextFieldBorderStyle(
+ /// color: Colors.black,
+ /// width: 1,
+ /// );
+ ///
+ /// final copy = style.copyWith(
+ /// width: 2,
+ /// );
+ ///
+ /// print(copy.color); // black
+ /// print(copy.width); // 2
+ /// ```
+ @useResult FTextFieldBorderStyle copyWith({
Color? color,
double? width,
BorderRadius? radius,
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.destructive-raw-badge-content.png b/forui/test/golden/badge/zinc-dark-FBadgeVariant.destructive-raw-badge-content.png
deleted file mode 100644
index 862d5f4fc..000000000
Binary files a/forui/test/golden/badge/zinc-dark-FBadgeVariant.destructive-raw-badge-content.png and /dev/null differ
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.destructive-text-badge-content.png b/forui/test/golden/badge/zinc-dark-FBadgeVariant.destructive-text-badge-content.png
deleted file mode 100644
index 862d5f4fc..000000000
Binary files a/forui/test/golden/badge/zinc-dark-FBadgeVariant.destructive-text-badge-content.png and /dev/null differ
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.primary-raw-badge-content.png b/forui/test/golden/badge/zinc-dark-Variant.destructive-raw-badge-content.png
similarity index 65%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.primary-raw-badge-content.png
rename to forui/test/golden/badge/zinc-dark-Variant.destructive-raw-badge-content.png
index f3162779e..852f5c06e 100644
Binary files a/forui/test/golden/badge/zinc-light-FBadgeVariant.primary-raw-badge-content.png and b/forui/test/golden/badge/zinc-dark-Variant.destructive-raw-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.destructive-raw-content.png b/forui/test/golden/badge/zinc-dark-Variant.destructive-raw-content.png
similarity index 100%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.destructive-raw-content.png
rename to forui/test/golden/badge/zinc-dark-Variant.destructive-raw-content.png
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.primary-text-badge-content.png b/forui/test/golden/badge/zinc-dark-Variant.destructive-text-badge-content.png
similarity index 65%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.primary-text-badge-content.png
rename to forui/test/golden/badge/zinc-dark-Variant.destructive-text-badge-content.png
index f3162779e..852f5c06e 100644
Binary files a/forui/test/golden/badge/zinc-light-FBadgeVariant.primary-text-badge-content.png and b/forui/test/golden/badge/zinc-dark-Variant.destructive-text-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.primary-raw-badge-content.png b/forui/test/golden/badge/zinc-dark-Variant.outline-raw-badge-content.png
similarity index 57%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.primary-raw-badge-content.png
rename to forui/test/golden/badge/zinc-dark-Variant.outline-raw-badge-content.png
index d23304fa8..edf3f6a76 100644
Binary files a/forui/test/golden/badge/zinc-dark-FBadgeVariant.primary-raw-badge-content.png and b/forui/test/golden/badge/zinc-dark-Variant.outline-raw-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.outline-raw-content.png b/forui/test/golden/badge/zinc-dark-Variant.outline-raw-content.png
similarity index 100%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.outline-raw-content.png
rename to forui/test/golden/badge/zinc-dark-Variant.outline-raw-content.png
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.primary-text-badge-content.png b/forui/test/golden/badge/zinc-dark-Variant.outline-text-badge-content.png
similarity index 57%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.primary-text-badge-content.png
rename to forui/test/golden/badge/zinc-dark-Variant.outline-text-badge-content.png
index d23304fa8..edf3f6a76 100644
Binary files a/forui/test/golden/badge/zinc-dark-FBadgeVariant.primary-text-badge-content.png and b/forui/test/golden/badge/zinc-dark-Variant.outline-text-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-dark-Variant.primary-raw-badge-content.png b/forui/test/golden/badge/zinc-dark-Variant.primary-raw-badge-content.png
new file mode 100644
index 000000000..51e617f3c
Binary files /dev/null and b/forui/test/golden/badge/zinc-dark-Variant.primary-raw-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.primary-raw-content.png b/forui/test/golden/badge/zinc-dark-Variant.primary-raw-content.png
similarity index 100%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.primary-raw-content.png
rename to forui/test/golden/badge/zinc-dark-Variant.primary-raw-content.png
diff --git a/forui/test/golden/badge/zinc-dark-Variant.primary-text-badge-content.png b/forui/test/golden/badge/zinc-dark-Variant.primary-text-badge-content.png
new file mode 100644
index 000000000..51e617f3c
Binary files /dev/null and b/forui/test/golden/badge/zinc-dark-Variant.primary-text-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-dark-Variant.secondary-raw-badge-content.png b/forui/test/golden/badge/zinc-dark-Variant.secondary-raw-badge-content.png
new file mode 100644
index 000000000..d190ddf8d
Binary files /dev/null and b/forui/test/golden/badge/zinc-dark-Variant.secondary-raw-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.secondary-raw-content.png b/forui/test/golden/badge/zinc-dark-Variant.secondary-raw-content.png
similarity index 100%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.secondary-raw-content.png
rename to forui/test/golden/badge/zinc-dark-Variant.secondary-raw-content.png
diff --git a/forui/test/golden/badge/zinc-dark-Variant.secondary-text-badge-content.png b/forui/test/golden/badge/zinc-dark-Variant.secondary-text-badge-content.png
new file mode 100644
index 000000000..d190ddf8d
Binary files /dev/null and b/forui/test/golden/badge/zinc-dark-Variant.secondary-text-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.destructive-raw-badge-content.png b/forui/test/golden/badge/zinc-light-FBadgeVariant.destructive-raw-badge-content.png
deleted file mode 100644
index 320bda7eb..000000000
Binary files a/forui/test/golden/badge/zinc-light-FBadgeVariant.destructive-raw-badge-content.png and /dev/null differ
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.destructive-text-badge-content.png b/forui/test/golden/badge/zinc-light-FBadgeVariant.destructive-text-badge-content.png
deleted file mode 100644
index 320bda7eb..000000000
Binary files a/forui/test/golden/badge/zinc-light-FBadgeVariant.destructive-text-badge-content.png and /dev/null differ
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.secondary-raw-badge-content.png b/forui/test/golden/badge/zinc-light-Variant.destructive-raw-badge-content.png
similarity index 63%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.secondary-raw-badge-content.png
rename to forui/test/golden/badge/zinc-light-Variant.destructive-raw-badge-content.png
index ab2c1677b..e75e8ed3c 100644
Binary files a/forui/test/golden/badge/zinc-dark-FBadgeVariant.secondary-raw-badge-content.png and b/forui/test/golden/badge/zinc-light-Variant.destructive-raw-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.destructive-raw-content.png b/forui/test/golden/badge/zinc-light-Variant.destructive-raw-content.png
similarity index 100%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.destructive-raw-content.png
rename to forui/test/golden/badge/zinc-light-Variant.destructive-raw-content.png
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.secondary-text-badge-content.png b/forui/test/golden/badge/zinc-light-Variant.destructive-text-badge-content.png
similarity index 63%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.secondary-text-badge-content.png
rename to forui/test/golden/badge/zinc-light-Variant.destructive-text-badge-content.png
index ab2c1677b..e75e8ed3c 100644
Binary files a/forui/test/golden/badge/zinc-dark-FBadgeVariant.secondary-text-badge-content.png and b/forui/test/golden/badge/zinc-light-Variant.destructive-text-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.outline-raw-badge-content.png b/forui/test/golden/badge/zinc-light-Variant.outline-raw-badge-content.png
similarity index 53%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.outline-raw-badge-content.png
rename to forui/test/golden/badge/zinc-light-Variant.outline-raw-badge-content.png
index 4ad642ac3..ba2865582 100644
Binary files a/forui/test/golden/badge/zinc-dark-FBadgeVariant.outline-raw-badge-content.png and b/forui/test/golden/badge/zinc-light-Variant.outline-raw-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.outline-raw-content.png b/forui/test/golden/badge/zinc-light-Variant.outline-raw-content.png
similarity index 100%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.outline-raw-content.png
rename to forui/test/golden/badge/zinc-light-Variant.outline-raw-content.png
diff --git a/forui/test/golden/badge/zinc-dark-FBadgeVariant.outline-text-badge-content.png b/forui/test/golden/badge/zinc-light-Variant.outline-text-badge-content.png
similarity index 53%
rename from forui/test/golden/badge/zinc-dark-FBadgeVariant.outline-text-badge-content.png
rename to forui/test/golden/badge/zinc-light-Variant.outline-text-badge-content.png
index 4ad642ac3..ba2865582 100644
Binary files a/forui/test/golden/badge/zinc-dark-FBadgeVariant.outline-text-badge-content.png and b/forui/test/golden/badge/zinc-light-Variant.outline-text-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.outline-raw-badge-content.png b/forui/test/golden/badge/zinc-light-Variant.primary-raw-badge-content.png
similarity index 59%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.outline-raw-badge-content.png
rename to forui/test/golden/badge/zinc-light-Variant.primary-raw-badge-content.png
index 152c49ec0..932110f89 100644
Binary files a/forui/test/golden/badge/zinc-light-FBadgeVariant.outline-raw-badge-content.png and b/forui/test/golden/badge/zinc-light-Variant.primary-raw-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.primary-raw-content.png b/forui/test/golden/badge/zinc-light-Variant.primary-raw-content.png
similarity index 100%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.primary-raw-content.png
rename to forui/test/golden/badge/zinc-light-Variant.primary-raw-content.png
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.outline-text-badge-content.png b/forui/test/golden/badge/zinc-light-Variant.primary-text-badge-content.png
similarity index 59%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.outline-text-badge-content.png
rename to forui/test/golden/badge/zinc-light-Variant.primary-text-badge-content.png
index 152c49ec0..932110f89 100644
Binary files a/forui/test/golden/badge/zinc-light-FBadgeVariant.outline-text-badge-content.png and b/forui/test/golden/badge/zinc-light-Variant.primary-text-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.secondary-raw-badge-content.png b/forui/test/golden/badge/zinc-light-Variant.secondary-raw-badge-content.png
similarity index 70%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.secondary-raw-badge-content.png
rename to forui/test/golden/badge/zinc-light-Variant.secondary-raw-badge-content.png
index 7477e6029..66d4e0442 100644
Binary files a/forui/test/golden/badge/zinc-light-FBadgeVariant.secondary-raw-badge-content.png and b/forui/test/golden/badge/zinc-light-Variant.secondary-raw-badge-content.png differ
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.secondary-raw-content.png b/forui/test/golden/badge/zinc-light-Variant.secondary-raw-content.png
similarity index 100%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.secondary-raw-content.png
rename to forui/test/golden/badge/zinc-light-Variant.secondary-raw-content.png
diff --git a/forui/test/golden/badge/zinc-light-FBadgeVariant.secondary-text-badge-content.png b/forui/test/golden/badge/zinc-light-Variant.secondary-text-badge-content.png
similarity index 70%
rename from forui/test/golden/badge/zinc-light-FBadgeVariant.secondary-text-badge-content.png
rename to forui/test/golden/badge/zinc-light-Variant.secondary-text-badge-content.png
index 7477e6029..66d4e0442 100644
Binary files a/forui/test/golden/badge/zinc-light-FBadgeVariant.secondary-text-badge-content.png and b/forui/test/golden/badge/zinc-light-Variant.secondary-text-badge-content.png differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.destructive-disabled-button-content.png b/forui/test/golden/button/zinc-dark-FButtonVariant.destructive-disabled-button-content.png
deleted file mode 100644
index 2dbb03e6d..000000000
Binary files a/forui/test/golden/button/zinc-dark-FButtonVariant.destructive-disabled-button-content.png and /dev/null differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.destructive-enabled-button-content.png b/forui/test/golden/button/zinc-dark-FButtonVariant.destructive-enabled-button-content.png
deleted file mode 100644
index 46daf75eb..000000000
Binary files a/forui/test/golden/button/zinc-dark-FButtonVariant.destructive-enabled-button-content.png and /dev/null differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.primary-enabled-button-content.png b/forui/test/golden/button/zinc-dark-FButtonVariant.primary-enabled-button-content.png
deleted file mode 100644
index 7e3e7f7b0..000000000
Binary files a/forui/test/golden/button/zinc-dark-FButtonVariant.primary-enabled-button-content.png and /dev/null differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.secondary-disabled-button-content.png b/forui/test/golden/button/zinc-dark-FButtonVariant.secondary-disabled-button-content.png
deleted file mode 100644
index 721d21df0..000000000
Binary files a/forui/test/golden/button/zinc-dark-FButtonVariant.secondary-disabled-button-content.png and /dev/null differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.outline-disabled-button-content.png b/forui/test/golden/button/zinc-dark-Variant.destructive-disabled-button-content.png
similarity index 52%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.outline-disabled-button-content.png
rename to forui/test/golden/button/zinc-dark-Variant.destructive-disabled-button-content.png
index 1d244d672..c1a56444d 100644
Binary files a/forui/test/golden/button/zinc-dark-FButtonVariant.outline-disabled-button-content.png and b/forui/test/golden/button/zinc-dark-Variant.destructive-disabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.destructive-disabled-raw-content.png b/forui/test/golden/button/zinc-dark-Variant.destructive-disabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.destructive-disabled-raw-content.png
rename to forui/test/golden/button/zinc-dark-Variant.destructive-disabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-dark-Variant.destructive-enabled-button-content.png b/forui/test/golden/button/zinc-dark-Variant.destructive-enabled-button-content.png
new file mode 100644
index 000000000..7bf9f1cc3
Binary files /dev/null and b/forui/test/golden/button/zinc-dark-Variant.destructive-enabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.destructive-enabled-raw-content.png b/forui/test/golden/button/zinc-dark-Variant.destructive-enabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.destructive-enabled-raw-content.png
rename to forui/test/golden/button/zinc-dark-Variant.destructive-enabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-dark-Variant.outline-disabled-button-content.png b/forui/test/golden/button/zinc-dark-Variant.outline-disabled-button-content.png
new file mode 100644
index 000000000..88df4a935
Binary files /dev/null and b/forui/test/golden/button/zinc-dark-Variant.outline-disabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.outline-disabled-raw-content.png b/forui/test/golden/button/zinc-dark-Variant.outline-disabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.outline-disabled-raw-content.png
rename to forui/test/golden/button/zinc-dark-Variant.outline-disabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-dark-Variant.outline-enabled-button-content.png b/forui/test/golden/button/zinc-dark-Variant.outline-enabled-button-content.png
new file mode 100644
index 000000000..effa0053e
Binary files /dev/null and b/forui/test/golden/button/zinc-dark-Variant.outline-enabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.outline-enabled-raw-content.png b/forui/test/golden/button/zinc-dark-Variant.outline-enabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.outline-enabled-raw-content.png
rename to forui/test/golden/button/zinc-dark-Variant.outline-enabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.primary-disabled-button-content.png b/forui/test/golden/button/zinc-dark-Variant.primary-disabled-button-content.png
similarity index 59%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.primary-disabled-button-content.png
rename to forui/test/golden/button/zinc-dark-Variant.primary-disabled-button-content.png
index fa0f554af..dfe43a958 100644
Binary files a/forui/test/golden/button/zinc-dark-FButtonVariant.primary-disabled-button-content.png and b/forui/test/golden/button/zinc-dark-Variant.primary-disabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.primary-disabled-raw-content.png b/forui/test/golden/button/zinc-dark-Variant.primary-disabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.primary-disabled-raw-content.png
rename to forui/test/golden/button/zinc-dark-Variant.primary-disabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.outline-enabled-button-content.png b/forui/test/golden/button/zinc-dark-Variant.primary-enabled-button-content.png
similarity index 51%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.outline-enabled-button-content.png
rename to forui/test/golden/button/zinc-dark-Variant.primary-enabled-button-content.png
index eb9221b23..db442bdd4 100644
Binary files a/forui/test/golden/button/zinc-dark-FButtonVariant.outline-enabled-button-content.png and b/forui/test/golden/button/zinc-dark-Variant.primary-enabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.primary-enabled-raw-content.png b/forui/test/golden/button/zinc-dark-Variant.primary-enabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.primary-enabled-raw-content.png
rename to forui/test/golden/button/zinc-dark-Variant.primary-enabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-dark-Variant.secondary-disabled-button-content.png b/forui/test/golden/button/zinc-dark-Variant.secondary-disabled-button-content.png
new file mode 100644
index 000000000..b0df6c978
Binary files /dev/null and b/forui/test/golden/button/zinc-dark-Variant.secondary-disabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.secondary-disabled-raw-content.png b/forui/test/golden/button/zinc-dark-Variant.secondary-disabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.secondary-disabled-raw-content.png
rename to forui/test/golden/button/zinc-dark-Variant.secondary-disabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.secondary-enabled-button-content.png b/forui/test/golden/button/zinc-dark-Variant.secondary-enabled-button-content.png
similarity index 56%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.secondary-enabled-button-content.png
rename to forui/test/golden/button/zinc-dark-Variant.secondary-enabled-button-content.png
index df13b4775..68c6ffaf5 100644
Binary files a/forui/test/golden/button/zinc-dark-FButtonVariant.secondary-enabled-button-content.png and b/forui/test/golden/button/zinc-dark-Variant.secondary-enabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-dark-FButtonVariant.secondary-enabled-raw-content.png b/forui/test/golden/button/zinc-dark-Variant.secondary-enabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-dark-FButtonVariant.secondary-enabled-raw-content.png
rename to forui/test/golden/button/zinc-dark-Variant.secondary-enabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.destructive-disabled-button-content.png b/forui/test/golden/button/zinc-light-FButtonVariant.destructive-disabled-button-content.png
deleted file mode 100644
index 811f86e4d..000000000
Binary files a/forui/test/golden/button/zinc-light-FButtonVariant.destructive-disabled-button-content.png and /dev/null differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.destructive-enabled-button-content.png b/forui/test/golden/button/zinc-light-FButtonVariant.destructive-enabled-button-content.png
deleted file mode 100644
index 2113bd3dc..000000000
Binary files a/forui/test/golden/button/zinc-light-FButtonVariant.destructive-enabled-button-content.png and /dev/null differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.outline-enabled-button-content.png b/forui/test/golden/button/zinc-light-FButtonVariant.outline-enabled-button-content.png
deleted file mode 100644
index 5db85d579..000000000
Binary files a/forui/test/golden/button/zinc-light-FButtonVariant.outline-enabled-button-content.png and /dev/null differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.primary-disabled-button-content.png b/forui/test/golden/button/zinc-light-FButtonVariant.primary-disabled-button-content.png
deleted file mode 100644
index 8ff1fdef2..000000000
Binary files a/forui/test/golden/button/zinc-light-FButtonVariant.primary-disabled-button-content.png and /dev/null differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.secondary-disabled-button-content.png b/forui/test/golden/button/zinc-light-FButtonVariant.secondary-disabled-button-content.png
deleted file mode 100644
index eddd1aac9..000000000
Binary files a/forui/test/golden/button/zinc-light-FButtonVariant.secondary-disabled-button-content.png and /dev/null differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.secondary-enabled-button-content.png b/forui/test/golden/button/zinc-light-Variant.destructive-disabled-button-content.png
similarity index 50%
rename from forui/test/golden/button/zinc-light-FButtonVariant.secondary-enabled-button-content.png
rename to forui/test/golden/button/zinc-light-Variant.destructive-disabled-button-content.png
index 3c4f00355..181943bbe 100644
Binary files a/forui/test/golden/button/zinc-light-FButtonVariant.secondary-enabled-button-content.png and b/forui/test/golden/button/zinc-light-Variant.destructive-disabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.destructive-disabled-raw-content.png b/forui/test/golden/button/zinc-light-Variant.destructive-disabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-light-FButtonVariant.destructive-disabled-raw-content.png
rename to forui/test/golden/button/zinc-light-Variant.destructive-disabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-light-Variant.destructive-enabled-button-content.png b/forui/test/golden/button/zinc-light-Variant.destructive-enabled-button-content.png
new file mode 100644
index 000000000..ebec052d9
Binary files /dev/null and b/forui/test/golden/button/zinc-light-Variant.destructive-enabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.destructive-enabled-raw-content.png b/forui/test/golden/button/zinc-light-Variant.destructive-enabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-light-FButtonVariant.destructive-enabled-raw-content.png
rename to forui/test/golden/button/zinc-light-Variant.destructive-enabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.outline-disabled-button-content.png b/forui/test/golden/button/zinc-light-Variant.outline-disabled-button-content.png
similarity index 58%
rename from forui/test/golden/button/zinc-light-FButtonVariant.outline-disabled-button-content.png
rename to forui/test/golden/button/zinc-light-Variant.outline-disabled-button-content.png
index 74f73bdeb..77b15abfc 100644
Binary files a/forui/test/golden/button/zinc-light-FButtonVariant.outline-disabled-button-content.png and b/forui/test/golden/button/zinc-light-Variant.outline-disabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.outline-disabled-raw-content.png b/forui/test/golden/button/zinc-light-Variant.outline-disabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-light-FButtonVariant.outline-disabled-raw-content.png
rename to forui/test/golden/button/zinc-light-Variant.outline-disabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.primary-enabled-button-content.png b/forui/test/golden/button/zinc-light-Variant.outline-enabled-button-content.png
similarity index 52%
rename from forui/test/golden/button/zinc-light-FButtonVariant.primary-enabled-button-content.png
rename to forui/test/golden/button/zinc-light-Variant.outline-enabled-button-content.png
index 6cd3e1746..9520937e0 100644
Binary files a/forui/test/golden/button/zinc-light-FButtonVariant.primary-enabled-button-content.png and b/forui/test/golden/button/zinc-light-Variant.outline-enabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.outline-enabled-raw-content.png b/forui/test/golden/button/zinc-light-Variant.outline-enabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-light-FButtonVariant.outline-enabled-raw-content.png
rename to forui/test/golden/button/zinc-light-Variant.outline-enabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-light-Variant.primary-disabled-button-content.png b/forui/test/golden/button/zinc-light-Variant.primary-disabled-button-content.png
new file mode 100644
index 000000000..d697dada1
Binary files /dev/null and b/forui/test/golden/button/zinc-light-Variant.primary-disabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.primary-disabled-raw-content.png b/forui/test/golden/button/zinc-light-Variant.primary-disabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-light-FButtonVariant.primary-disabled-raw-content.png
rename to forui/test/golden/button/zinc-light-Variant.primary-disabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-light-Variant.primary-enabled-button-content.png b/forui/test/golden/button/zinc-light-Variant.primary-enabled-button-content.png
new file mode 100644
index 000000000..16ed97b54
Binary files /dev/null and b/forui/test/golden/button/zinc-light-Variant.primary-enabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.primary-enabled-raw-content.png b/forui/test/golden/button/zinc-light-Variant.primary-enabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-light-FButtonVariant.primary-enabled-raw-content.png
rename to forui/test/golden/button/zinc-light-Variant.primary-enabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-light-Variant.secondary-disabled-button-content.png b/forui/test/golden/button/zinc-light-Variant.secondary-disabled-button-content.png
new file mode 100644
index 000000000..2bd9623c3
Binary files /dev/null and b/forui/test/golden/button/zinc-light-Variant.secondary-disabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.secondary-disabled-raw-content.png b/forui/test/golden/button/zinc-light-Variant.secondary-disabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-light-FButtonVariant.secondary-disabled-raw-content.png
rename to forui/test/golden/button/zinc-light-Variant.secondary-disabled-raw-content.png
diff --git a/forui/test/golden/button/zinc-light-Variant.secondary-enabled-button-content.png b/forui/test/golden/button/zinc-light-Variant.secondary-enabled-button-content.png
new file mode 100644
index 000000000..ac1da6c0e
Binary files /dev/null and b/forui/test/golden/button/zinc-light-Variant.secondary-enabled-button-content.png differ
diff --git a/forui/test/golden/button/zinc-light-FButtonVariant.secondary-enabled-raw-content.png b/forui/test/golden/button/zinc-light-Variant.secondary-enabled-raw-content.png
similarity index 100%
rename from forui/test/golden/button/zinc-light-FButtonVariant.secondary-enabled-raw-content.png
rename to forui/test/golden/button/zinc-light-Variant.secondary-enabled-raw-content.png
diff --git a/forui/test/golden/card/zinc-dark-raw-card-content.png b/forui/test/golden/card/zinc-dark-raw-card-content.png
index 386dc5ef3..8b71b1c29 100644
Binary files a/forui/test/golden/card/zinc-dark-raw-card-content.png and b/forui/test/golden/card/zinc-dark-raw-card-content.png differ
diff --git a/forui/test/golden/card/zinc-dark-text-card-content.png b/forui/test/golden/card/zinc-dark-text-card-content.png
index 386dc5ef3..8b71b1c29 100644
Binary files a/forui/test/golden/card/zinc-dark-text-card-content.png and b/forui/test/golden/card/zinc-dark-text-card-content.png differ
diff --git a/forui/test/golden/card/zinc-light-raw-card-content.png b/forui/test/golden/card/zinc-light-raw-card-content.png
index 7feb996ed..2dbf01b92 100644
Binary files a/forui/test/golden/card/zinc-light-raw-card-content.png and b/forui/test/golden/card/zinc-light-raw-card-content.png differ
diff --git a/forui/test/golden/card/zinc-light-text-card-content.png b/forui/test/golden/card/zinc-light-text-card-content.png
index 7feb996ed..2dbf01b92 100644
Binary files a/forui/test/golden/card/zinc-light-text-card-content.png and b/forui/test/golden/card/zinc-light-text-card-content.png differ
diff --git a/forui/test/golden/dialog/zinc-dark-Axis.horizontal-raw-dialog-content.png b/forui/test/golden/dialog/zinc-dark-Axis.horizontal-raw-dialog-content.png
new file mode 100644
index 000000000..4558c75c6
Binary files /dev/null and b/forui/test/golden/dialog/zinc-dark-Axis.horizontal-raw-dialog-content.png differ
diff --git a/forui/test/golden/dialog/zinc-dark-Axis.horizontal-text-dialog-content.png b/forui/test/golden/dialog/zinc-dark-Axis.horizontal-text-dialog-content.png
new file mode 100644
index 000000000..4558c75c6
Binary files /dev/null and b/forui/test/golden/dialog/zinc-dark-Axis.horizontal-text-dialog-content.png differ
diff --git a/forui/test/golden/dialog/zinc-dark-Axis.vertical-raw-dialog-content.png b/forui/test/golden/dialog/zinc-dark-Axis.vertical-raw-dialog-content.png
new file mode 100644
index 000000000..ad2e6080a
Binary files /dev/null and b/forui/test/golden/dialog/zinc-dark-Axis.vertical-raw-dialog-content.png differ
diff --git a/forui/test/golden/dialog/zinc-dark-Axis.vertical-text-dialog-content.png b/forui/test/golden/dialog/zinc-dark-Axis.vertical-text-dialog-content.png
new file mode 100644
index 000000000..ad2e6080a
Binary files /dev/null and b/forui/test/golden/dialog/zinc-dark-Axis.vertical-text-dialog-content.png differ
diff --git a/forui/test/golden/dialog/zinc-dark-FDialogAlignment.horizontal-raw-dialog-content.png b/forui/test/golden/dialog/zinc-dark-FDialogAlignment.horizontal-raw-dialog-content.png
deleted file mode 100644
index 6e0bac4d3..000000000
Binary files a/forui/test/golden/dialog/zinc-dark-FDialogAlignment.horizontal-raw-dialog-content.png and /dev/null differ
diff --git a/forui/test/golden/dialog/zinc-dark-FDialogAlignment.horizontal-text-dialog-content.png b/forui/test/golden/dialog/zinc-dark-FDialogAlignment.horizontal-text-dialog-content.png
deleted file mode 100644
index 6e0bac4d3..000000000
Binary files a/forui/test/golden/dialog/zinc-dark-FDialogAlignment.horizontal-text-dialog-content.png and /dev/null differ
diff --git a/forui/test/golden/dialog/zinc-dark-FDialogAlignment.vertical-raw-dialog-content.png b/forui/test/golden/dialog/zinc-dark-FDialogAlignment.vertical-raw-dialog-content.png
deleted file mode 100644
index f0150b091..000000000
Binary files a/forui/test/golden/dialog/zinc-dark-FDialogAlignment.vertical-raw-dialog-content.png and /dev/null differ
diff --git a/forui/test/golden/dialog/zinc-dark-FDialogAlignment.vertical-text-dialog-content.png b/forui/test/golden/dialog/zinc-dark-FDialogAlignment.vertical-text-dialog-content.png
deleted file mode 100644
index f0150b091..000000000
Binary files a/forui/test/golden/dialog/zinc-dark-FDialogAlignment.vertical-text-dialog-content.png and /dev/null differ
diff --git a/forui/test/golden/dialog/zinc-light-Axis.horizontal-raw-dialog-content.png b/forui/test/golden/dialog/zinc-light-Axis.horizontal-raw-dialog-content.png
new file mode 100644
index 000000000..360a4b851
Binary files /dev/null and b/forui/test/golden/dialog/zinc-light-Axis.horizontal-raw-dialog-content.png differ
diff --git a/forui/test/golden/dialog/zinc-light-Axis.horizontal-text-dialog-content.png b/forui/test/golden/dialog/zinc-light-Axis.horizontal-text-dialog-content.png
new file mode 100644
index 000000000..360a4b851
Binary files /dev/null and b/forui/test/golden/dialog/zinc-light-Axis.horizontal-text-dialog-content.png differ
diff --git a/forui/test/golden/dialog/zinc-light-Axis.vertical-raw-dialog-content.png b/forui/test/golden/dialog/zinc-light-Axis.vertical-raw-dialog-content.png
new file mode 100644
index 000000000..c3596ee8d
Binary files /dev/null and b/forui/test/golden/dialog/zinc-light-Axis.vertical-raw-dialog-content.png differ
diff --git a/forui/test/golden/dialog/zinc-light-Axis.vertical-text-dialog-content.png b/forui/test/golden/dialog/zinc-light-Axis.vertical-text-dialog-content.png
new file mode 100644
index 000000000..c3596ee8d
Binary files /dev/null and b/forui/test/golden/dialog/zinc-light-Axis.vertical-text-dialog-content.png differ
diff --git a/forui/test/golden/dialog/zinc-light-FDialogAlignment.horizontal-raw-dialog-content.png b/forui/test/golden/dialog/zinc-light-FDialogAlignment.horizontal-raw-dialog-content.png
deleted file mode 100644
index ba9a0b1f9..000000000
Binary files a/forui/test/golden/dialog/zinc-light-FDialogAlignment.horizontal-raw-dialog-content.png and /dev/null differ
diff --git a/forui/test/golden/dialog/zinc-light-FDialogAlignment.horizontal-text-dialog-content.png b/forui/test/golden/dialog/zinc-light-FDialogAlignment.horizontal-text-dialog-content.png
deleted file mode 100644
index ba9a0b1f9..000000000
Binary files a/forui/test/golden/dialog/zinc-light-FDialogAlignment.horizontal-text-dialog-content.png and /dev/null differ
diff --git a/forui/test/golden/dialog/zinc-light-FDialogAlignment.vertical-raw-dialog-content.png b/forui/test/golden/dialog/zinc-light-FDialogAlignment.vertical-raw-dialog-content.png
deleted file mode 100644
index 8a0c8c260..000000000
Binary files a/forui/test/golden/dialog/zinc-light-FDialogAlignment.vertical-raw-dialog-content.png and /dev/null differ
diff --git a/forui/test/golden/dialog/zinc-light-FDialogAlignment.vertical-text-dialog-content.png b/forui/test/golden/dialog/zinc-light-FDialogAlignment.vertical-text-dialog-content.png
deleted file mode 100644
index 8a0c8c260..000000000
Binary files a/forui/test/golden/dialog/zinc-light-FDialogAlignment.vertical-text-dialog-content.png and /dev/null differ
diff --git a/forui/test/golden/header/zinc-dark-header.png b/forui/test/golden/header/zinc-dark-header.png
index a99ee2519..67d60b833 100644
Binary files a/forui/test/golden/header/zinc-dark-header.png and b/forui/test/golden/header/zinc-dark-header.png differ
diff --git a/forui/test/golden/header/zinc-dark-raw-title.png b/forui/test/golden/header/zinc-dark-raw-title.png
index 72dcab638..5aa4d358b 100644
Binary files a/forui/test/golden/header/zinc-dark-raw-title.png and b/forui/test/golden/header/zinc-dark-raw-title.png differ
diff --git a/forui/test/golden/header/zinc-light-header.png b/forui/test/golden/header/zinc-light-header.png
index eea9fcee0..58cf6863f 100644
Binary files a/forui/test/golden/header/zinc-light-header.png and b/forui/test/golden/header/zinc-light-header.png differ
diff --git a/forui/test/golden/header/zinc-light-raw-title.png b/forui/test/golden/header/zinc-light-raw-title.png
index 753eab311..70090d4bc 100644
Binary files a/forui/test/golden/header/zinc-light-raw-title.png and b/forui/test/golden/header/zinc-light-raw-title.png differ
diff --git a/forui/test/golden/text_field/default-zinc-dark-focused-no-text.png b/forui/test/golden/text_field/default-zinc-dark-focused-no-text.png
index a0971e19b..df7216740 100644
Binary files a/forui/test/golden/text_field/default-zinc-dark-focused-no-text.png and b/forui/test/golden/text_field/default-zinc-dark-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-dark-focused-raw-text.png b/forui/test/golden/text_field/default-zinc-dark-focused-raw-text.png
index a2e0127be..e1e23653e 100644
Binary files a/forui/test/golden/text_field/default-zinc-dark-focused-raw-text.png and b/forui/test/golden/text_field/default-zinc-dark-focused-raw-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-dark-focused-text.png b/forui/test/golden/text_field/default-zinc-dark-focused-text.png
index 25faae303..a5a36d426 100644
Binary files a/forui/test/golden/text_field/default-zinc-dark-focused-text.png and b/forui/test/golden/text_field/default-zinc-dark-focused-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-dark-unfocused-no-text.png b/forui/test/golden/text_field/default-zinc-dark-unfocused-no-text.png
index 8e7b13fa4..8719adb9f 100644
Binary files a/forui/test/golden/text_field/default-zinc-dark-unfocused-no-text.png and b/forui/test/golden/text_field/default-zinc-dark-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-dark-unfocused-raw-text.png b/forui/test/golden/text_field/default-zinc-dark-unfocused-raw-text.png
index 7a1e46320..3c5610f57 100644
Binary files a/forui/test/golden/text_field/default-zinc-dark-unfocused-raw-text.png and b/forui/test/golden/text_field/default-zinc-dark-unfocused-raw-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-dark-unfocused-text.png b/forui/test/golden/text_field/default-zinc-dark-unfocused-text.png
index bad7d3367..65c2fb5b8 100644
Binary files a/forui/test/golden/text_field/default-zinc-dark-unfocused-text.png and b/forui/test/golden/text_field/default-zinc-dark-unfocused-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-light-focused-no-text.png b/forui/test/golden/text_field/default-zinc-light-focused-no-text.png
index 22095100a..ca9e8f9db 100644
Binary files a/forui/test/golden/text_field/default-zinc-light-focused-no-text.png and b/forui/test/golden/text_field/default-zinc-light-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-light-focused-raw-text.png b/forui/test/golden/text_field/default-zinc-light-focused-raw-text.png
index 95870e393..53d6e6956 100644
Binary files a/forui/test/golden/text_field/default-zinc-light-focused-raw-text.png and b/forui/test/golden/text_field/default-zinc-light-focused-raw-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-light-focused-text.png b/forui/test/golden/text_field/default-zinc-light-focused-text.png
index 63b5fc75e..3f5153450 100644
Binary files a/forui/test/golden/text_field/default-zinc-light-focused-text.png and b/forui/test/golden/text_field/default-zinc-light-focused-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-light-unfocused-no-text.png b/forui/test/golden/text_field/default-zinc-light-unfocused-no-text.png
index f8447c986..75e61a4b3 100644
Binary files a/forui/test/golden/text_field/default-zinc-light-unfocused-no-text.png and b/forui/test/golden/text_field/default-zinc-light-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-light-unfocused-raw-text.png b/forui/test/golden/text_field/default-zinc-light-unfocused-raw-text.png
index c0a0eb39b..055e84d17 100644
Binary files a/forui/test/golden/text_field/default-zinc-light-unfocused-raw-text.png and b/forui/test/golden/text_field/default-zinc-light-unfocused-raw-text.png differ
diff --git a/forui/test/golden/text_field/default-zinc-light-unfocused-text.png b/forui/test/golden/text_field/default-zinc-light-unfocused-text.png
index aa94e58e3..4285cb9c5 100644
Binary files a/forui/test/golden/text_field/default-zinc-light-unfocused-text.png and b/forui/test/golden/text_field/default-zinc-light-unfocused-text.png differ
diff --git a/forui/test/golden/text_field/email-zinc-dark-focused-no-text.png b/forui/test/golden/text_field/email-zinc-dark-focused-no-text.png
index 414170fea..a8766fa44 100644
Binary files a/forui/test/golden/text_field/email-zinc-dark-focused-no-text.png and b/forui/test/golden/text_field/email-zinc-dark-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/email-zinc-dark-focused-text.png b/forui/test/golden/text_field/email-zinc-dark-focused-text.png
index c1b8e08bf..fe940ee26 100644
Binary files a/forui/test/golden/text_field/email-zinc-dark-focused-text.png and b/forui/test/golden/text_field/email-zinc-dark-focused-text.png differ
diff --git a/forui/test/golden/text_field/email-zinc-dark-unfocused-no-text.png b/forui/test/golden/text_field/email-zinc-dark-unfocused-no-text.png
index 45bb933c1..bc90b17fb 100644
Binary files a/forui/test/golden/text_field/email-zinc-dark-unfocused-no-text.png and b/forui/test/golden/text_field/email-zinc-dark-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/email-zinc-dark-unfocused-text.png b/forui/test/golden/text_field/email-zinc-dark-unfocused-text.png
index 2f646e22e..e534fcd91 100644
Binary files a/forui/test/golden/text_field/email-zinc-dark-unfocused-text.png and b/forui/test/golden/text_field/email-zinc-dark-unfocused-text.png differ
diff --git a/forui/test/golden/text_field/email-zinc-light-focused-no-text.png b/forui/test/golden/text_field/email-zinc-light-focused-no-text.png
index b6f6a3cc2..a5326f8c4 100644
Binary files a/forui/test/golden/text_field/email-zinc-light-focused-no-text.png and b/forui/test/golden/text_field/email-zinc-light-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/email-zinc-light-focused-text.png b/forui/test/golden/text_field/email-zinc-light-focused-text.png
index 284dbc672..2d7206399 100644
Binary files a/forui/test/golden/text_field/email-zinc-light-focused-text.png and b/forui/test/golden/text_field/email-zinc-light-focused-text.png differ
diff --git a/forui/test/golden/text_field/email-zinc-light-unfocused-no-text.png b/forui/test/golden/text_field/email-zinc-light-unfocused-no-text.png
index 6e04cf61b..158e091a3 100644
Binary files a/forui/test/golden/text_field/email-zinc-light-unfocused-no-text.png and b/forui/test/golden/text_field/email-zinc-light-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/email-zinc-light-unfocused-text.png b/forui/test/golden/text_field/email-zinc-light-unfocused-text.png
index 5172c1229..cf22a7ed7 100644
Binary files a/forui/test/golden/text_field/email-zinc-light-unfocused-text.png and b/forui/test/golden/text_field/email-zinc-light-unfocused-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-dark-focused-no-text.png b/forui/test/golden/text_field/error-zinc-dark-focused-no-text.png
index f37078e31..719fb52b6 100644
Binary files a/forui/test/golden/text_field/error-zinc-dark-focused-no-text.png and b/forui/test/golden/text_field/error-zinc-dark-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-dark-focused-raw-text.png b/forui/test/golden/text_field/error-zinc-dark-focused-raw-text.png
index 2dcc9ea3c..89e13da48 100644
Binary files a/forui/test/golden/text_field/error-zinc-dark-focused-raw-text.png and b/forui/test/golden/text_field/error-zinc-dark-focused-raw-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-dark-focused-text.png b/forui/test/golden/text_field/error-zinc-dark-focused-text.png
index d850eab0e..c13339ece 100644
Binary files a/forui/test/golden/text_field/error-zinc-dark-focused-text.png and b/forui/test/golden/text_field/error-zinc-dark-focused-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-dark-unfocused-no-text.png b/forui/test/golden/text_field/error-zinc-dark-unfocused-no-text.png
index 595def582..aa9dc5d10 100644
Binary files a/forui/test/golden/text_field/error-zinc-dark-unfocused-no-text.png and b/forui/test/golden/text_field/error-zinc-dark-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-dark-unfocused-raw-text.png b/forui/test/golden/text_field/error-zinc-dark-unfocused-raw-text.png
index c8784e4c8..6d30d592e 100644
Binary files a/forui/test/golden/text_field/error-zinc-dark-unfocused-raw-text.png and b/forui/test/golden/text_field/error-zinc-dark-unfocused-raw-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-dark-unfocused-text.png b/forui/test/golden/text_field/error-zinc-dark-unfocused-text.png
index 92a1cb6e8..be449fc83 100644
Binary files a/forui/test/golden/text_field/error-zinc-dark-unfocused-text.png and b/forui/test/golden/text_field/error-zinc-dark-unfocused-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-light-focused-no-text.png b/forui/test/golden/text_field/error-zinc-light-focused-no-text.png
index 61ec8378d..e717b0c76 100644
Binary files a/forui/test/golden/text_field/error-zinc-light-focused-no-text.png and b/forui/test/golden/text_field/error-zinc-light-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-light-focused-raw-text.png b/forui/test/golden/text_field/error-zinc-light-focused-raw-text.png
index a5bb434a2..55d0d672c 100644
Binary files a/forui/test/golden/text_field/error-zinc-light-focused-raw-text.png and b/forui/test/golden/text_field/error-zinc-light-focused-raw-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-light-focused-text.png b/forui/test/golden/text_field/error-zinc-light-focused-text.png
index 465cae999..dd90350bb 100644
Binary files a/forui/test/golden/text_field/error-zinc-light-focused-text.png and b/forui/test/golden/text_field/error-zinc-light-focused-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-light-unfocused-no-text.png b/forui/test/golden/text_field/error-zinc-light-unfocused-no-text.png
index 83125d37f..46c86b8d1 100644
Binary files a/forui/test/golden/text_field/error-zinc-light-unfocused-no-text.png and b/forui/test/golden/text_field/error-zinc-light-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-light-unfocused-raw-text.png b/forui/test/golden/text_field/error-zinc-light-unfocused-raw-text.png
index b0b0f3240..77ad0e4bc 100644
Binary files a/forui/test/golden/text_field/error-zinc-light-unfocused-raw-text.png and b/forui/test/golden/text_field/error-zinc-light-unfocused-raw-text.png differ
diff --git a/forui/test/golden/text_field/error-zinc-light-unfocused-text.png b/forui/test/golden/text_field/error-zinc-light-unfocused-text.png
index b871a892d..74ed0f72c 100644
Binary files a/forui/test/golden/text_field/error-zinc-light-unfocused-text.png and b/forui/test/golden/text_field/error-zinc-light-unfocused-text.png differ
diff --git a/forui/test/golden/text_field/multiline-zinc-dark-focused-no-text.png b/forui/test/golden/text_field/multiline-zinc-dark-focused-no-text.png
index 6c64bd7f5..8c53bf32f 100644
Binary files a/forui/test/golden/text_field/multiline-zinc-dark-focused-no-text.png and b/forui/test/golden/text_field/multiline-zinc-dark-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/multiline-zinc-dark-focused-text.png b/forui/test/golden/text_field/multiline-zinc-dark-focused-text.png
index daa675dd7..17ece5b32 100644
Binary files a/forui/test/golden/text_field/multiline-zinc-dark-focused-text.png and b/forui/test/golden/text_field/multiline-zinc-dark-focused-text.png differ
diff --git a/forui/test/golden/text_field/multiline-zinc-dark-unfocused-no-text.png b/forui/test/golden/text_field/multiline-zinc-dark-unfocused-no-text.png
index 1928d1fa4..2a5f35f50 100644
Binary files a/forui/test/golden/text_field/multiline-zinc-dark-unfocused-no-text.png and b/forui/test/golden/text_field/multiline-zinc-dark-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/multiline-zinc-dark-unfocused-text.png b/forui/test/golden/text_field/multiline-zinc-dark-unfocused-text.png
index fa3b77738..8c2ff5842 100644
Binary files a/forui/test/golden/text_field/multiline-zinc-dark-unfocused-text.png and b/forui/test/golden/text_field/multiline-zinc-dark-unfocused-text.png differ
diff --git a/forui/test/golden/text_field/multiline-zinc-light-focused-no-text.png b/forui/test/golden/text_field/multiline-zinc-light-focused-no-text.png
index 1f9fcf650..52dccb3da 100644
Binary files a/forui/test/golden/text_field/multiline-zinc-light-focused-no-text.png and b/forui/test/golden/text_field/multiline-zinc-light-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/multiline-zinc-light-focused-text.png b/forui/test/golden/text_field/multiline-zinc-light-focused-text.png
index 0f34bef89..884a834a1 100644
Binary files a/forui/test/golden/text_field/multiline-zinc-light-focused-text.png and b/forui/test/golden/text_field/multiline-zinc-light-focused-text.png differ
diff --git a/forui/test/golden/text_field/multiline-zinc-light-unfocused-no-text.png b/forui/test/golden/text_field/multiline-zinc-light-unfocused-no-text.png
index 3ec65d60b..a696e5454 100644
Binary files a/forui/test/golden/text_field/multiline-zinc-light-unfocused-no-text.png and b/forui/test/golden/text_field/multiline-zinc-light-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/multiline-zinc-light-unfocused-text.png b/forui/test/golden/text_field/multiline-zinc-light-unfocused-text.png
index 4c06afe80..db22901dc 100644
Binary files a/forui/test/golden/text_field/multiline-zinc-light-unfocused-text.png and b/forui/test/golden/text_field/multiline-zinc-light-unfocused-text.png differ
diff --git a/forui/test/golden/text_field/password-zinc-dark-focused-no-text.png b/forui/test/golden/text_field/password-zinc-dark-focused-no-text.png
index db10bf479..a57679ba5 100644
Binary files a/forui/test/golden/text_field/password-zinc-dark-focused-no-text.png and b/forui/test/golden/text_field/password-zinc-dark-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/password-zinc-dark-focused-text.png b/forui/test/golden/text_field/password-zinc-dark-focused-text.png
index fe5196125..c20569ebd 100644
Binary files a/forui/test/golden/text_field/password-zinc-dark-focused-text.png and b/forui/test/golden/text_field/password-zinc-dark-focused-text.png differ
diff --git a/forui/test/golden/text_field/password-zinc-dark-unfocused-no-text.png b/forui/test/golden/text_field/password-zinc-dark-unfocused-no-text.png
index 9bf104208..edab691ec 100644
Binary files a/forui/test/golden/text_field/password-zinc-dark-unfocused-no-text.png and b/forui/test/golden/text_field/password-zinc-dark-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/password-zinc-dark-unfocused-text.png b/forui/test/golden/text_field/password-zinc-dark-unfocused-text.png
index 9f31ef685..145614a3f 100644
Binary files a/forui/test/golden/text_field/password-zinc-dark-unfocused-text.png and b/forui/test/golden/text_field/password-zinc-dark-unfocused-text.png differ
diff --git a/forui/test/golden/text_field/password-zinc-light-focused-no-text.png b/forui/test/golden/text_field/password-zinc-light-focused-no-text.png
index 74384304c..948c48fb2 100644
Binary files a/forui/test/golden/text_field/password-zinc-light-focused-no-text.png and b/forui/test/golden/text_field/password-zinc-light-focused-no-text.png differ
diff --git a/forui/test/golden/text_field/password-zinc-light-focused-text.png b/forui/test/golden/text_field/password-zinc-light-focused-text.png
index 30f3620f9..c1a8c6093 100644
Binary files a/forui/test/golden/text_field/password-zinc-light-focused-text.png and b/forui/test/golden/text_field/password-zinc-light-focused-text.png differ
diff --git a/forui/test/golden/text_field/password-zinc-light-unfocused-no-text.png b/forui/test/golden/text_field/password-zinc-light-unfocused-no-text.png
index ca5a86653..b12453454 100644
Binary files a/forui/test/golden/text_field/password-zinc-light-unfocused-no-text.png and b/forui/test/golden/text_field/password-zinc-light-unfocused-no-text.png differ
diff --git a/forui/test/golden/text_field/password-zinc-light-unfocused-text.png b/forui/test/golden/text_field/password-zinc-light-unfocused-text.png
index 9ea182b1e..37b7b43a8 100644
Binary files a/forui/test/golden/text_field/password-zinc-light-unfocused-text.png and b/forui/test/golden/text_field/password-zinc-light-unfocused-text.png differ
diff --git a/forui/test/src/theme/typoegraphy_test.dart b/forui/test/src/theme/typoegraphy_test.dart
deleted file mode 100644
index 0a84db1ae..000000000
--- a/forui/test/src/theme/typoegraphy_test.dart
+++ /dev/null
@@ -1,200 +0,0 @@
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-
-import 'package:flutter_test/flutter_test.dart';
-
-import 'package:forui/forui.dart';
-
-void main() {
- group('FTypography', () {
- const typography = FTypography(
- defaultFontFamily: 'Roboto',
- sizeScalar: 2,
- letterSpacingScalar: 3,
- wordSpacingScalar: 4,
- heightScalar: 5,
- );
-
- group('constructor', () {
- test('no arguments', () {
- const typography = FTypography();
- expect(typography.defaultFontFamily, 'packages/forui/Inter');
- expect(typography.sizeScalar, 1);
- expect(typography.letterSpacingScalar, 1);
- expect(typography.wordSpacingScalar, 1);
- expect(typography.heightScalar, 1);
- });
-
- test('blank font family', () => expect(() => FTypography(defaultFontFamily: ''), throwsAssertionError));
-
- test('sizeScalar is 0', () => expect(() => FTypography(sizeScalar: 0), throwsAssertionError));
-
- test('sizeScalar is NaN', () => expect(() => FTypography(sizeScalar: double.nan), throwsAssertionError));
-
- test('letterSpacingScalar is 0', () => expect(() => FTypography(letterSpacingScalar: 0), throwsAssertionError));
-
- test('letterSpacingScalar is NaN',
- () => expect(() => FTypography(letterSpacingScalar: double.nan), throwsAssertionError));
-
- test('wordSpacingScalar is 0', () => expect(() => FTypography(wordSpacingScalar: 0), throwsAssertionError));
-
- test('wordSpacingScalar is NaN', () => expect(() => FTypography(wordSpacingScalar: double.nan), throwsAssertionError));
-
- test('heightScalar is 0', () => expect(() => FTypography(heightScalar: 0), throwsAssertionError));
-
- test('heightScalar is NaN', () => expect(() => FTypography(heightScalar: double.nan), throwsAssertionError));
- });
-
- group('copyWith(...)', () {
- test('no arguments', () {
- typography.copyWith();
-
- expect(typography.defaultFontFamily, 'Roboto');
- expect(typography.sizeScalar, 2);
- expect(typography.letterSpacingScalar, 3);
- expect(typography.wordSpacingScalar, 4);
- expect(typography.heightScalar, 5);
- });
-
- test('all arguments', () {
- final typography = const FTypography().copyWith(
- defaultFontFamily: 'Roboto',
- sizeScalar: 2,
- letterSpacingScalar: 3,
- wordSpacingScalar: 4,
- heightScalar: 5,
- );
-
- expect(typography.defaultFontFamily, 'Roboto');
- expect(typography.sizeScalar, 2);
- expect(typography.letterSpacingScalar, 3);
- expect(typography.wordSpacingScalar, 4);
- expect(typography.heightScalar, 5);
- });
- });
-
- group('toTextStyle(...)', () {
- test('no arguments', () {
- final style = typography.toTextStyle();
-
- expect(style.fontFamily, 'Roboto');
- expect(style.fontSize, null);
- expect(style.letterSpacing, null);
- expect(style.wordSpacing, null);
- expect(style.height, null);
- });
-
- test('scaled arguments', () {
- final style = typography.toTextStyle(
- fontSize: 7,
- letterSpacing: 11,
- wordSpacing: 13,
- height: 17,
- );
-
- expect(style.fontFamily, 'Roboto');
- expect(style.fontSize, 14);
- expect(style.letterSpacing, 33);
- expect(style.wordSpacing, 52);
- expect(style.height, 85);
- });
-
- test('other arguments', () {
- final style = typography.toTextStyle(
- color: const Color(0xFF000000),
- );
-
- expect(style.color, const Color(0xFF000000));
- });
- });
-
- test('debugFillProperties', () {
- const font = FTypography(
- defaultFontFamily: 'Roboto',
- sizeScalar: 2,
- letterSpacingScalar: 3,
- wordSpacingScalar: 4,
- heightScalar: 5,
- xs: 6,
- sm: 7,
- base: 8,
- lg: 9,
- xl: 10,
- xl2: 11,
- xl3: 12,
- xl4: 13,
- xl5: 14,
- xl6: 15,
- xl7: 16,
- xl8: 17,
- );
-
- final builder = DiagnosticPropertiesBuilder();
- font.debugFillProperties(builder);
-
- expect(
- builder.properties.map((p) => p.toString()),
- [
- StringProperty('family', 'Roboto'),
- DoubleProperty('sizeScalar', 2),
- DoubleProperty('letterSpacingScalar', 3),
- DoubleProperty('wordSpacingScalar', 4),
- DoubleProperty('heightScalar', 5),
- DoubleProperty('xs', 6),
- DoubleProperty('sm', 7),
- DoubleProperty('base', 8),
- DoubleProperty('lg', 9),
- DoubleProperty('xl', 10),
- DoubleProperty('xl2', 11),
- DoubleProperty('xl3', 12),
- DoubleProperty('xl4', 13),
- DoubleProperty('xl5', 14),
- DoubleProperty('xl6', 15),
- DoubleProperty('xl7', 16),
- DoubleProperty('xl8', 17),
- ].map((p) => p.toString()));
- });
-
- group('equality and hashcode', () {
- test('equal', () {
- final copy = typography.copyWith();
- expect(copy, typography);
- expect(copy.hashCode, typography.hashCode);
- });
-
- test('not equal', () {
- final copy = typography.copyWith(defaultFontFamily: 'Else');
- expect(copy, isNot(typography));
- expect(copy.hashCode, isNot(typography.hashCode));
- });
- });
- });
-
- group('FontTextStyle', () {
- const font = FTypography(
- defaultFontFamily: 'Roboto',
- sizeScalar: 2,
- letterSpacingScalar: 3,
- wordSpacingScalar: 4,
- heightScalar: 5,
- );
-
- test('scale(...)', () {
- final style = const TextStyle(
- color: Colors.blueAccent,
- fontFamily: 'default-font',
- fontSize: 7,
- letterSpacing: 11,
- wordSpacing: 13,
- height: 17,
- ).scale(font);
-
- expect(style.color, Colors.blueAccent);
- expect(style.fontFamily, 'default-font');
- expect(style.fontSize, 14);
- expect(style.letterSpacing, 33);
- expect(style.wordSpacing, 52);
- expect(style.height, 85);
- });
- });
-}
diff --git a/forui/test/src/theme/typography_test.dart b/forui/test/src/theme/typography_test.dart
new file mode 100644
index 000000000..a878abe42
--- /dev/null
+++ b/forui/test/src/theme/typography_test.dart
@@ -0,0 +1,228 @@
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:forui/forui.dart';
+
+void main() {
+ group('FTypography', () {
+ FTypography typography = const FTypography();
+
+ setUp(() {
+ typography = const FTypography(
+ defaultFontFamily: 'Roboto',
+ xs: TextStyle(fontSize: 1),
+ sm: TextStyle(fontSize: 2),
+ base: TextStyle(fontSize: 3),
+ lg: TextStyle(fontSize: 4),
+ xl: TextStyle(fontSize: 5),
+ xl2: TextStyle(fontSize: 6),
+ xl3: TextStyle(fontSize: 7),
+ xl4: TextStyle(fontSize: 8),
+ xl5: TextStyle(fontSize: 9),
+ xl6: TextStyle(fontSize: 10),
+ xl7: TextStyle(fontSize: 11),
+ xl8: TextStyle(fontSize: 12),
+ );
+ });
+
+ group('constructor', () {
+ test('no arguments', () {
+ const typography = FTypography();
+
+ expect(typography.defaultFontFamily, 'packages/forui/Inter');
+ expect(typography.xs, const TextStyle(fontSize: 12, height: 1));
+ expect(typography.sm, const TextStyle(fontSize: 14, height: 1.25));
+ expect(typography.base, const TextStyle(fontSize: 16, height: 1.5));
+ expect(typography.lg, const TextStyle(fontSize: 18, height: 1.75));
+ expect(typography.xl, const TextStyle(fontSize: 20, height: 1.75));
+ expect(typography.xl2, const TextStyle(fontSize: 22, height: 2));
+ expect(typography.xl3, const TextStyle(fontSize: 30, height: 2.25));
+ expect(typography.xl4, const TextStyle(fontSize: 36, height: 2.5));
+ expect(typography.xl5, const TextStyle(fontSize: 48, height: 1));
+ expect(typography.xl6, const TextStyle(fontSize: 60, height: 1));
+ expect(typography.xl7, const TextStyle(fontSize: 72, height: 1));
+ expect(typography.xl8, const TextStyle(fontSize: 96, height: 1));
+ });
+
+ test('blank font family', () => expect(() => FTypography(defaultFontFamily: ''), throwsAssertionError));
+ });
+
+ group('inherit constructor', () {
+ const colorScheme = FColorScheme(
+ brightness: Brightness.light,
+ background: Colors.black,
+ foreground: Colors.black12,
+ primary: Colors.black26,
+ primaryForeground: Colors.black38,
+ secondary: Colors.black45,
+ secondaryForeground: Colors.black54,
+ muted: Colors.black87,
+ mutedForeground: Colors.blue,
+ destructive: Colors.blueAccent,
+ destructiveForeground: Colors.blueGrey,
+ error: Colors.red,
+ errorForeground: Colors.redAccent,
+ border: Colors.lightBlue,
+ );
+
+ test('no arguments', () {
+ typography = FTypography.inherit(colorScheme: colorScheme);
+
+ expect(typography.defaultFontFamily, 'packages/forui/Inter');
+ expect(typography.xs, TextStyle(color: colorScheme.foreground, fontSize: 12, height: 1));
+ expect(typography.sm, TextStyle(color: colorScheme.foreground, fontSize: 14, height: 1.25));
+ expect(typography.base, TextStyle(color: colorScheme.foreground, fontSize: 16, height: 1.5));
+ expect(typography.lg, TextStyle(color: colorScheme.foreground, fontSize: 18, height: 1.75));
+ expect(typography.xl, TextStyle(color: colorScheme.foreground, fontSize: 20, height: 1.75));
+ expect(typography.xl2, TextStyle(color: colorScheme.foreground, fontSize: 22, height: 2));
+ expect(typography.xl3, TextStyle(color: colorScheme.foreground, fontSize: 30, height: 2.25));
+ expect(typography.xl4, TextStyle(color: colorScheme.foreground, fontSize: 36, height: 2.5));
+ expect(typography.xl5, TextStyle(color: colorScheme.foreground, fontSize: 48, height: 1));
+ expect(typography.xl6, TextStyle(color: colorScheme.foreground, fontSize: 60, height: 1));
+ expect(typography.xl7, TextStyle(color: colorScheme.foreground, fontSize: 72, height: 1));
+ expect(typography.xl8, TextStyle(color: colorScheme.foreground, fontSize: 96, height: 1));
+ });
+
+ test(
+ 'blank font family',
+ () => expect(
+ () => FTypography.inherit(
+ colorScheme: colorScheme,
+ defaultFontFamily: '',
+ ),
+ throwsAssertionError,
+ ),
+ );
+ });
+
+ group('scale(...)', () {
+ test('no arguments', () {
+ typography = typography.scale();
+
+ expect(typography.defaultFontFamily, 'Roboto');
+ expect(typography.xs, const TextStyle(fontSize: 1));
+ expect(typography.sm, const TextStyle(fontSize: 2));
+ expect(typography.base, const TextStyle(fontSize: 3));
+ expect(typography.lg, const TextStyle(fontSize: 4));
+ expect(typography.xl, const TextStyle(fontSize: 5));
+ expect(typography.xl2, const TextStyle(fontSize: 6));
+ expect(typography.xl3, const TextStyle(fontSize: 7));
+ expect(typography.xl4, const TextStyle(fontSize: 8));
+ expect(typography.xl5, const TextStyle(fontSize: 9));
+ expect(typography.xl6, const TextStyle(fontSize: 10));
+ expect(typography.xl7, const TextStyle(fontSize: 11));
+ expect(typography.xl8, const TextStyle(fontSize: 12));
+ });
+
+ test('all arguments', () {
+ typography = typography.scale(sizeScalar: 10);
+
+ expect(typography.defaultFontFamily, 'Roboto');
+ expect(typography.xs, const TextStyle(fontSize: 10));
+ expect(typography.sm, const TextStyle(fontSize: 20));
+ expect(typography.base, const TextStyle(fontSize: 30));
+ expect(typography.lg, const TextStyle(fontSize: 40));
+ expect(typography.xl, const TextStyle(fontSize: 50));
+ expect(typography.xl2, const TextStyle(fontSize: 60));
+ expect(typography.xl3, const TextStyle(fontSize: 70));
+ expect(typography.xl4, const TextStyle(fontSize: 80));
+ expect(typography.xl5, const TextStyle(fontSize: 90));
+ expect(typography.xl6, const TextStyle(fontSize: 100));
+ expect(typography.xl7, const TextStyle(fontSize: 110));
+ expect(typography.xl8, const TextStyle(fontSize: 120));
+ });
+ });
+
+ group('copyWith(...)', () {
+ test('no arguments', () {
+ typography = const FTypography(defaultFontFamily: 'Roboto');
+ typography = typography.copyWith();
+
+ expect(typography.defaultFontFamily, 'Roboto');
+ expect(typography.xs, const TextStyle(fontSize: 12, height: 1));
+ expect(typography.sm, const TextStyle(fontSize: 14, height: 1.25));
+ expect(typography.base, const TextStyle(fontSize: 16, height: 1.5));
+ expect(typography.lg, const TextStyle(fontSize: 18, height: 1.75));
+ expect(typography.xl, const TextStyle(fontSize: 20, height: 1.75));
+ expect(typography.xl2, const TextStyle(fontSize: 22, height: 2));
+ expect(typography.xl3, const TextStyle(fontSize: 30, height: 2.25));
+ expect(typography.xl4, const TextStyle(fontSize: 36, height: 2.5));
+ expect(typography.xl5, const TextStyle(fontSize: 48, height: 1));
+ expect(typography.xl6, const TextStyle(fontSize: 60, height: 1));
+ expect(typography.xl7, const TextStyle(fontSize: 72, height: 1));
+ expect(typography.xl8, const TextStyle(fontSize: 96, height: 1));
+ });
+
+ test('all arguments', () {
+ final typography = const FTypography().copyWith(
+ defaultFontFamily: 'AnotherFont',
+ xs: const TextStyle(fontSize: 1),
+ sm: const TextStyle(fontSize: 2),
+ base: const TextStyle(fontSize: 3),
+ lg: const TextStyle(fontSize: 4),
+ xl: const TextStyle(fontSize: 5),
+ xl2: const TextStyle(fontSize: 6),
+ xl3: const TextStyle(fontSize: 7),
+ xl4: const TextStyle(fontSize: 8),
+ xl5: const TextStyle(fontSize: 9),
+ xl6: const TextStyle(fontSize: 10),
+ xl7: const TextStyle(fontSize: 11),
+ xl8: const TextStyle(fontSize: 12),
+ );
+
+ expect(typography.defaultFontFamily, 'AnotherFont');
+ expect(typography.xs, const TextStyle(fontSize: 1));
+ expect(typography.sm, const TextStyle(fontSize: 2));
+ expect(typography.base, const TextStyle(fontSize: 3));
+ expect(typography.lg, const TextStyle(fontSize: 4));
+ expect(typography.xl, const TextStyle(fontSize: 5));
+ expect(typography.xl2, const TextStyle(fontSize: 6));
+ expect(typography.xl3, const TextStyle(fontSize: 7));
+ expect(typography.xl4, const TextStyle(fontSize: 8));
+ expect(typography.xl5, const TextStyle(fontSize: 9));
+ expect(typography.xl6, const TextStyle(fontSize: 10));
+ expect(typography.xl7, const TextStyle(fontSize: 11));
+ expect(typography.xl8, const TextStyle(fontSize: 12));
+ });
+ });
+
+ test('debugFillProperties', () {
+ final builder = DiagnosticPropertiesBuilder();
+ typography.debugFillProperties(builder);
+
+ expect(
+ builder.properties.map((p) => p.toString()),
+ [
+ StringProperty('family', 'Roboto'),
+ DiagnosticsProperty('xs', const TextStyle(fontSize: 1)),
+ DiagnosticsProperty('sm', const TextStyle(fontSize: 2)),
+ DiagnosticsProperty('base', const TextStyle(fontSize: 3)),
+ DiagnosticsProperty('lg', const TextStyle(fontSize: 4)),
+ DiagnosticsProperty('xl', const TextStyle(fontSize: 5)),
+ DiagnosticsProperty('xl2', const TextStyle(fontSize: 6)),
+ DiagnosticsProperty('xl3', const TextStyle(fontSize: 7)),
+ DiagnosticsProperty('xl4', const TextStyle(fontSize: 8)),
+ DiagnosticsProperty('xl5', const TextStyle(fontSize: 9)),
+ DiagnosticsProperty('xl6', const TextStyle(fontSize: 10)),
+ DiagnosticsProperty('xl7', const TextStyle(fontSize: 11)),
+ DiagnosticsProperty('xl8', const TextStyle(fontSize: 12)),
+ ].map((p) => p.toString()));
+ });
+
+ group('equality and hashcode', () {
+ test('equal', () {
+ final copy = typography.copyWith();
+ expect(copy, typography);
+ expect(copy.hashCode, typography.hashCode);
+ });
+
+ test('not equal', () {
+ final copy = typography.copyWith(defaultFontFamily: 'Else');
+ expect(copy, isNot(typography));
+ expect(copy.hashCode, isNot(typography.hashCode));
+ });
+ });
+ });
+}
diff --git a/forui/test/src/widgets/badge/badge_golden_test.dart b/forui/test/src/widgets/badge/badge_golden_test.dart
index 5d4b9f937..092eba5df 100644
--- a/forui/test/src/widgets/badge/badge_golden_test.dart
+++ b/forui/test/src/widgets/badge/badge_golden_test.dart
@@ -5,13 +5,13 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
-import 'package:forui/forui.dart';
+import 'package:forui/src/widgets/badge/badge.dart';
import '../../test_scaffold.dart';
void main() {
group('FBadge', () {
for (final (name, theme, background) in TestScaffold.themes) {
- for (final variant in FBadgeVariant.values) {
+ for (final variant in Variant.values) {
testWidgets('$name with text FBadgeContent', (tester) async {
await tester.pumpWidget(
TestScaffold(
@@ -19,7 +19,7 @@ void main() {
background: background,
child: FBadge(
label: 'Badge',
- design: variant,
+ style: variant,
),
),
);
@@ -37,7 +37,7 @@ void main() {
background: background,
child: FBadge(
rawLabel: const Text('Badge'),
- design: variant,
+ style: variant,
),
),
);
@@ -55,7 +55,7 @@ void main() {
data: theme,
background: background,
child: FBadge.raw(
- design: variant,
+ style: variant,
builder: (_, style) => Padding(
padding: const EdgeInsets.all(50),
child: Container(
@@ -66,7 +66,7 @@ void main() {
width: 50,
height: 50,
decoration: BoxDecoration(
- color: style.background,
+ color: style.backgroundColor,
border: Border.all(
color: Colors.blueAccent,
width: 2,
diff --git a/forui/test/src/widgets/button_golden_test.dart b/forui/test/src/widgets/button_golden_test.dart
index 39175baed..e09bce3f3 100644
--- a/forui/test/src/widgets/button_golden_test.dart
+++ b/forui/test/src/widgets/button_golden_test.dart
@@ -6,12 +6,13 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:forui/forui.dart';
+import 'package:forui/src/widgets/button/button.dart';
import '../test_scaffold.dart';
void main() {
group('FButton', () {
for (final (name, theme, _) in TestScaffold.themes) {
- for (final variant in FButtonVariant.values) {
+ for (final variant in Variant.values) {
testWidgets('$name enabled with FButtonContent', (tester) async {
await tester.pumpWidget(
TestScaffold(
@@ -20,7 +21,7 @@ void main() {
padding: const EdgeInsets.symmetric(horizontal: 20),
child: FButton(
label: 'Button',
- design: variant,
+ style: variant,
prefixIcon: FButtonIcon(icon: FAssets.icons.circlePlay),
suffixIcon: FButtonIcon(icon: FAssets.icons.circleStop),
onPress: () {},
@@ -43,7 +44,7 @@ void main() {
padding: const EdgeInsets.symmetric(horizontal: 20),
child: FButton(
label: 'Button',
- design: variant,
+ style: variant,
prefixIcon: FButtonIcon(icon: FAssets.icons.circlePlay),
suffixIcon: FButtonIcon(icon: FAssets.icons.circleStop),
onPress: null,
@@ -65,7 +66,7 @@ void main() {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: FButton.raw(
- design: variant,
+ style: variant,
onPress: () {},
child: Padding(
padding: const EdgeInsets.all(50),
@@ -104,7 +105,7 @@ void main() {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: FButton.raw(
- design: variant,
+ style: variant,
onPress: null,
child: Padding(
padding: const EdgeInsets.all(50),
diff --git a/forui/test/src/widgets/dialog/dialog_golden_test.dart b/forui/test/src/widgets/dialog/dialog_golden_test.dart
index ff2990987..304869177 100644
--- a/forui/test/src/widgets/dialog/dialog_golden_test.dart
+++ b/forui/test/src/widgets/dialog/dialog_golden_test.dart
@@ -7,23 +7,23 @@ import 'package:forui/forui.dart';
import '../../test_scaffold.dart';
class UnderTest extends StatelessWidget {
- final FDialogAlignment alignment;
+ final Axis direction;
final bool raw;
- const UnderTest({required this.alignment, required this.raw, super.key});
+ const UnderTest({required this.direction, required this.raw, super.key});
@override
Widget build(BuildContext context) {
final actions = [
FButton(label: 'Continue', onPress: () {}),
- FButton(design: FButtonVariant.outline, label: 'Cancel', onPress: () {
+ FButton(style: FButtonStyle.outline, label: 'Cancel', onPress: () {
Navigator.of(context).pop();
}),
];
if (raw) {
return FDialog(
- alignment: alignment,
+ direction: direction,
rawTitle: const Text('Are you absolutely sure?'),
rawBody: const Text('This action cannot be undone. This will permanently delete your account and remove your data from our servers.'),
actions: actions,
@@ -31,7 +31,7 @@ class UnderTest extends StatelessWidget {
} else {
return FDialog(
- alignment: alignment,
+ direction: direction,
title: 'Are you absolutely sure?',
body: 'This action cannot be undone. This will permanently delete your account and remove your data from our servers.',
actions: actions,
@@ -43,7 +43,7 @@ class UnderTest extends StatelessWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
- ..add(EnumProperty('alignment', alignment))
+ ..add(EnumProperty('alignment', direction))
..add(DiagnosticsProperty('raw', raw));
}
}
@@ -52,38 +52,38 @@ class UnderTest extends StatelessWidget {
void main() {
group('FDialog', () {
for (final (name, theme, background) in TestScaffold.themes) {
- for (final alignment in [FDialogAlignment.horizontal, FDialogAlignment.vertical]) {
- testWidgets('$name with $alignment text FDialogContent', (tester) async {
+ for (final direction in Axis.values) {
+ testWidgets('$name with $direction text FDialogContent', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: TestScaffold(
data: theme,
background: background,
- child: UnderTest(alignment: alignment, raw: false),
+ child: UnderTest(direction: direction, raw: false),
),
),
);
await expectLater(
find.byType(UnderTest),
- matchesGoldenFile('dialog/$name-$alignment-text-dialog-content.png'),
+ matchesGoldenFile('dialog/$name-$direction-text-dialog-content.png'),
);
});
- testWidgets('$name with $alignment raw FDialogContent', (tester) async {
+ testWidgets('$name with $direction raw FDialogContent', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: TestScaffold(
data: theme,
background: background,
- child: UnderTest(alignment: alignment, raw: true),
+ child: UnderTest(direction: direction, raw: true),
),
),
);
await expectLater(
find.byType(UnderTest),
- matchesGoldenFile('dialog/$name-$alignment-raw-dialog-content.png'),
+ matchesGoldenFile('dialog/$name-$direction-raw-dialog-content.png'),
);
});
}
diff --git a/forui/test/src/widgets/text_field/flutter_test_config.dart b/forui/test/src/widgets/text_field/flutter_test_config.dart
index 69418f0ba..dc2942590 100644
--- a/forui/test/src/widgets/text_field/flutter_test_config.dart
+++ b/forui/test/src/widgets/text_field/flutter_test_config.dart
@@ -2,7 +2,7 @@ import 'dart:async';
import '../../flutter_test_config.dart';
-const _kGoldenTestsThreshold = 4 / 100;
+const _kGoldenTestsThreshold = 5 / 100;
Future testExecutable(FutureOr Function() testMain) async {
await configureGoldenTests(_kGoldenTestsThreshold);
diff --git a/samples/.gitignore b/samples/.gitignore
index 29a3a5017..3db624ea7 100644
--- a/samples/.gitignore
+++ b/samples/.gitignore
@@ -41,3 +41,5 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
+
+samples/lib/main.gr.dart
diff --git a/samples/ios/Podfile b/samples/ios/Podfile
new file mode 100644
index 000000000..c9339a034
--- /dev/null
+++ b/samples/ios/Podfile
@@ -0,0 +1,41 @@
+# Uncomment this line to define a global platform for your project
+# platform :ios, '12.0'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
+target 'Runner' do
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+ target 'RunnerTests' do
+ inherit! :search_paths
+ end
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_ios_build_settings(target)
+ end
+end
diff --git a/samples/lib/main.dart b/samples/lib/main.dart
index 979bd2762..4583422d0 100644
--- a/samples/lib/main.dart
+++ b/samples/lib/main.dart
@@ -1,11 +1,8 @@
-// Flutter imports:
import 'package:flutter/material.dart' hide DialogRoute;
-// Package imports:
import 'package:auto_route/auto_route.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
-// Project imports:
import 'package:forui_samples/main.gr.dart';
void main() {
diff --git a/samples/lib/main.gr.dart b/samples/lib/main.gr.dart
index 45730456a..dba4def44 100644
--- a/samples/lib/main.gr.dart
+++ b/samples/lib/main.gr.dart
@@ -32,8 +32,8 @@ abstract class $_AppRouter extends _i10.RootStackRouter {
'theme',
'zinc-light',
),
- variant: queryParams.getString(
- 'variant',
+ style: queryParams.getString(
+ 'style',
'primary',
),
));
@@ -41,7 +41,7 @@ abstract class $_AppRouter extends _i10.RootStackRouter {
routeData: routeData,
child: _i1.BadgePage(
theme: args.theme,
- variant: args.variant,
+ style: args.style,
),
);
},
@@ -200,17 +200,17 @@ abstract class $_AppRouter extends _i10.RootStackRouter {
class BadgeRoute extends _i10.PageRouteInfo {
BadgeRoute({
String theme = 'zinc-light',
- String variant = 'primary',
+ String style = 'primary',
List<_i10.PageRouteInfo>? children,
}) : super(
BadgeRoute.name,
args: BadgeRouteArgs(
theme: theme,
- variant: variant,
+ style: style,
),
rawQueryParams: {
'theme': theme,
- 'variant': variant,
+ 'style': style,
},
initialChildren: children,
);
@@ -224,16 +224,16 @@ class BadgeRoute extends _i10.PageRouteInfo {
class BadgeRouteArgs {
const BadgeRouteArgs({
this.theme = 'zinc-light',
- this.variant = 'primary',
+ this.style = 'primary',
});
final String theme;
- final String variant;
+ final String style;
@override
String toString() {
- return 'BadgeRouteArgs{theme: $theme, variant: $variant}';
+ return 'BadgeRouteArgs{theme: $theme, style: $style}';
}
}
diff --git a/samples/lib/sample_scaffold.dart b/samples/lib/sample_scaffold.dart
index 4d198f6da..5b9b05101 100644
--- a/samples/lib/sample_scaffold.dart
+++ b/samples/lib/sample_scaffold.dart
@@ -1,7 +1,5 @@
-// Flutter imports:
import 'package:flutter/material.dart';
-// Package imports:
import 'package:forui/forui.dart';
/// The themes.
diff --git a/samples/lib/widgets/badge.dart b/samples/lib/widgets/badge.dart
index 351dbd43e..bf15b3dab 100644
--- a/samples/lib/widgets/badge.dart
+++ b/samples/lib/widgets/badge.dart
@@ -1,31 +1,30 @@
-// Flutter imports:
+// ignore_for_file: invalid_use_of_internal_member, implementation_imports
+
import 'package:flutter/material.dart';
-// Package imports:
import 'package:auto_route/auto_route.dart';
-import 'package:forui/forui.dart';
+import 'package:forui/src/widgets/badge/badge.dart';
-// Project imports:
import 'package:forui_samples/sample_scaffold.dart';
@RoutePage()
class BadgePage extends SampleScaffold {
- static final variants = {
- for (final value in FBadgeVariant.values)
+ static final styles = {
+ for (final value in Variant.values)
value.name: value,
};
- final FBadgeVariant variant;
+ final FBadgeStyle style;
BadgePage({
@queryParam super.theme,
- @queryParam String variant = 'primary',
+ @queryParam String style = 'primary',
}):
- variant = variants[variant]!;
+ style = styles[style]!;
@override
Widget child(BuildContext context) => FBadge(
label: 'Badge',
- design: variant,
+ style: style,
);
}
diff --git a/samples/lib/widgets/button.dart b/samples/lib/widgets/button.dart
index 10a3956d3..52ffdcb94 100644
--- a/samples/lib/widgets/button.dart
+++ b/samples/lib/widgets/button.dart
@@ -1,21 +1,21 @@
-// Flutter imports:
import 'package:flutter/material.dart';
-// Package imports:
import 'package:auto_route/auto_route.dart';
import 'package:forui/forui.dart';
+import 'package:forui/src/widgets/button/button.dart';
-// Project imports:
import 'package:forui_samples/sample_scaffold.dart';
+// ignore_for_file: invalid_use_of_internal_member, implementation_imports
+
final variants = {
- for (final value in FButtonVariant.values)
+ for (final value in Variant.values)
value.name: value,
};
@RoutePage()
class ButtonTextPage extends SampleScaffold {
- final FButtonVariant variant;
+ final Variant variant;
final String label;
ButtonTextPage({
@@ -23,13 +23,13 @@ class ButtonTextPage extends SampleScaffold {
@queryParam String variant = 'primary',
@queryParam this.label = 'Button',
}):
- variant = variants[variant] ?? FButtonVariant.primary;
+ variant = variants[variant] ?? Variant.primary;
@override
Widget child(BuildContext context) => IntrinsicWidth(
child: FButton(
label: label,
- design: variant,
+ style: variant,
onPress: () { },
),
);
@@ -37,7 +37,7 @@ class ButtonTextPage extends SampleScaffold {
@RoutePage()
class ButtonIconPage extends SampleScaffold {
- final FButtonVariant variant;
+ final Variant variant;
ButtonIconPage({
@queryParam super.theme = 'zinc-light',
@@ -50,7 +50,7 @@ class ButtonIconPage extends SampleScaffold {
child: FButton(
prefixIcon: FButtonIcon(icon: FAssets.icons.mail),
label: 'Login with Email',
- design: variant,
+ style: variant,
onPress: () { },
),
);
diff --git a/samples/lib/widgets/card.dart b/samples/lib/widgets/card.dart
index 280e7ab52..088c5efd9 100644
--- a/samples/lib/widgets/card.dart
+++ b/samples/lib/widgets/card.dart
@@ -1,11 +1,8 @@
-// Flutter imports:
import 'package:flutter/material.dart';
-// Package imports:
import 'package:auto_route/auto_route.dart';
import 'package:forui/forui.dart';
-// Project imports:
import 'package:forui_samples/sample_scaffold.dart';
@RoutePage()
diff --git a/samples/lib/widgets/dialog.dart b/samples/lib/widgets/dialog.dart
index 3ce37aac7..9f87d4a74 100644
--- a/samples/lib/widgets/dialog.dart
+++ b/samples/lib/widgets/dialog.dart
@@ -1,27 +1,24 @@
-// Flutter imports:
import 'package:flutter/material.dart';
-// Package imports:
import 'package:auto_route/auto_route.dart';
import 'package:forui/forui.dart';
-// Project imports:
import 'package:forui_samples/sample_scaffold.dart';
@RoutePage()
class DialogPage extends SampleScaffold {
- final FDialogAlignment alignment;
+ final Axis direction;
DialogPage({
@queryParam super.theme,
@queryParam bool vertical = false,
}):
- alignment = vertical ? FDialogAlignment.vertical : FDialogAlignment.horizontal;
+ direction = vertical ? Axis.vertical : Axis.horizontal;
@override
Widget child(BuildContext context) {
final actions = [
- FButton(design: FButtonVariant.outline, label: 'Cancel', onPress: () => Navigator.of(context).pop()),
+ FButton(style: FButtonStyle.outline, label: 'Cancel', onPress: () => Navigator.of(context).pop()),
FButton(label: 'Continue', onPress: () => Navigator.of(context).pop()),
];
@@ -34,10 +31,10 @@ class DialogPage extends SampleScaffold {
onPress: () => showAdaptiveDialog(
context: context,
builder: (context) => FDialog(
- alignment: alignment,
+ direction: direction,
title: 'Are you absolutely sure?',
body: 'This action cannot be undone. This will permanently delete your account and remove your data from our servers.',
- actions: alignment == FDialogAlignment.vertical ? actions.reversed.toList() : actions,
+ actions: direction == Axis.vertical ? actions.reversed.toList() : actions,
),
),
),
diff --git a/samples/lib/widgets/header.dart b/samples/lib/widgets/header.dart
index 810c09107..30454129e 100644
--- a/samples/lib/widgets/header.dart
+++ b/samples/lib/widgets/header.dart
@@ -1,11 +1,8 @@
-// Flutter imports:
import 'package:flutter/material.dart';
-// Package imports:
import 'package:auto_route/auto_route.dart';
import 'package:forui/forui.dart';
-// Project imports:
import 'package:forui_samples/sample_scaffold.dart';
@RoutePage()
diff --git a/samples/lib/widgets/separator.dart b/samples/lib/widgets/separator.dart
index de5ca2377..5f9960612 100644
--- a/samples/lib/widgets/separator.dart
+++ b/samples/lib/widgets/separator.dart
@@ -1,11 +1,8 @@
-// Flutter imports:
import 'package:flutter/material.dart';
-// Package imports:
import 'package:auto_route/auto_route.dart';
import 'package:forui/forui.dart';
-// Project imports:
import 'package:forui_samples/sample_scaffold.dart';
@RoutePage()
@@ -28,22 +25,33 @@ class SeparatorPage extends SampleScaffold {
children: [
Text(
'Forui',
- style: TextStyle(
- fontSize: typography.base,
- fontWeight: FontWeight.w600,
+ style: typography.base.copyWith(
color: colorScheme.foreground,
+ fontWeight: FontWeight.w600,
),
),
const FSeparator(),
- Text(
- 'An open-source UI component library.',
- style: TextStyle(
- fontSize: typography.sm,
- color: colorScheme.mutedForeground,
- ),
+ Row(
+ children: [
+ Text(
+ 'Forui',
+ style: typography.base.copyWith(
+ color: colorScheme.foreground,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ const FSeparator(vertical: true),
+ Text(
+ 'Forui',
+ style: typography.base.copyWith(
+ color: colorScheme.foreground,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ ],
),
],
- ),
+ ),
);
}
}
diff --git a/samples/lib/widgets/switch.dart b/samples/lib/widgets/switch.dart
index f741043e9..08c4f54a3 100644
--- a/samples/lib/widgets/switch.dart
+++ b/samples/lib/widgets/switch.dart
@@ -1,11 +1,8 @@
-// Flutter imports:
import 'package:flutter/material.dart';
-// Package imports:
import 'package:auto_route/auto_route.dart';
import 'package:forui/forui.dart';
-// Project imports:
import 'package:forui_samples/sample_scaffold.dart';
@RoutePage()
diff --git a/samples/lib/widgets/text_field.dart b/samples/lib/widgets/text_field.dart
index 386126479..8e52e8b81 100644
--- a/samples/lib/widgets/text_field.dart
+++ b/samples/lib/widgets/text_field.dart
@@ -1,11 +1,8 @@
-// Flutter imports:
import 'package:flutter/material.dart';
-// Package imports:
import 'package:auto_route/auto_route.dart';
import 'package:forui/forui.dart';
-// Project imports:
import 'package:forui_samples/sample_scaffold.dart';
@RoutePage()
diff --git a/samples/pubspec.yaml b/samples/pubspec.yaml
index 4fa0a5628..b480ae986 100644
--- a/samples/pubspec.yaml
+++ b/samples/pubspec.yaml
@@ -86,3 +86,7 @@ flutter:
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
+
+
+import_sorter:
+ comments: false