Skip to content

Commit

Permalink
Card variants (#84)
Browse files Browse the repository at this point in the history
* first draft

* Converted to seperate FAlert widget

* dart analysis fixes

* Golden tests implemented

* alert samples completed

* Alert ready for review

* fixed pr issues

* Converted to FAlertIcon

* Commit from GitHub Actions (Forui Presubmit)

* fixed again

* Update alert.dart

* Update alert.mdx

---------

Co-authored-by: Daviiddoo <Daviiddoo@users.noreply.github.com>
Co-authored-by: Matthias Ngeo <matthiasngeo@gmail.com>
  • Loading branch information
3 people authored Jul 16, 2024
1 parent b3ec8c8 commit fb76077
Show file tree
Hide file tree
Showing 21 changed files with 602 additions and 3 deletions.
64 changes: 64 additions & 0 deletions docs/pages/docs/alert.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Tabs } from 'nextra/components';
import { Widget } from "../../components/widget";

# Alert
Displays a callout for user attention.

<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='alert' query={{}}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
FAlert(
title: const Text('Heads Up!'),
subtitle: const Text('You can add components to your app using the cli.'),
);
```
</Tabs.Tab>
</Tabs>

## Usage

### `FAlert(...)`

```dart
FAlert(
icon: FAlertIcon(icon: FAssets.icons.badgeAlert),
title: const Text('Heads Up!'),
subtitle: const Text('You can add components to your app using the cli.'),
);
```

## Examples

### Primary
<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='alert' query={{}}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
FAlert(
title: const Text('Heads Up!'),
subtitle: const Text('You can add components to your app using the cli.'),
);
```
</Tabs.Tab>
</Tabs>

### Destructive
<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='alert' query={{style: 'destructive'}}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
FAlert(
title: const Text('Heads Up!'),
subtitle: const Text('You can add components to your app using the cli.'),
style: FAlertStyle.destructive,
);
```
</Tabs.Tab>
</Tabs>
1 change: 1 addition & 0 deletions forui/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Next

### Additions
* Add `FAlert`
* Add `FCalendar`
* Add `FBottomNavigationBar`

Expand Down
4 changes: 4 additions & 0 deletions forui/example/lib/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class _ExampleState extends State<Example> {
const SizedBox(height: 100),
FProgress(value: 0.9),
const SizedBox(height: 10),
FAlert(
title: const Text('Heads Up! Forui is coming to flutter!'),
subtitle: const Text('You can add components dfijsoi djfosfj to your app using the cli.'),
)
],
);
}
10 changes: 10 additions & 0 deletions forui/lib/src/theme/theme_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ final class FThemeData with Diagnosticable {
/// The style. It is used to configure the miscellaneous properties, such as border radii, of Forui widgets.
final FStyle style;

/// The alert styles.
final FAlertStyles alertStyles;

/// The badge styles.
final FBadgeStyles badgeStyles;

Expand Down Expand Up @@ -80,6 +83,7 @@ final class FThemeData with Diagnosticable {
required this.buttonStyles,
required this.calendarStyle,
required this.cardStyle,
required this.alertStyles,
required this.checkboxStyle,
required this.dialogStyle,
required this.headerStyle,
Expand All @@ -105,6 +109,7 @@ final class FThemeData with Diagnosticable {
colorScheme: colorScheme,
typography: typography,
style: style,
alertStyles: FAlertStyles.inherit(colorScheme: colorScheme, typography: typography, style: style),
badgeStyles: FBadgeStyles.inherit(colorScheme: colorScheme, typography: typography, style: style),
bottomNavigationBarStyle: FBottomNavigationBarStyle.inherit(colorScheme: colorScheme, typography: typography),
buttonStyles: FButtonStyles.inherit(colorScheme: colorScheme, typography: typography, style: style),
Expand Down Expand Up @@ -143,6 +148,7 @@ final class FThemeData with Diagnosticable {
FColorScheme? colorScheme,
FTypography? typography,
FStyle? style,
FAlertStyles? alertStyles,
FBadgeStyles? badgeStyles,
FBottomNavigationBarStyle? bottomNavigationBarStyle,
FButtonStyles? buttonStyles,
Expand All @@ -162,6 +168,7 @@ final class FThemeData with Diagnosticable {
colorScheme: colorScheme ?? this.colorScheme,
typography: typography ?? this.typography,
style: style ?? this.style,
alertStyles: alertStyles ?? this.alertStyles,
badgeStyles: badgeStyles ?? this.badgeStyles,
bottomNavigationBarStyle: bottomNavigationBarStyle ?? this.bottomNavigationBarStyle,
buttonStyles: buttonStyles ?? this.buttonStyles,
Expand All @@ -185,6 +192,7 @@ final class FThemeData with Diagnosticable {
..add(DiagnosticsProperty('colorScheme', colorScheme, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('typography', typography, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('style', style, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('alertStyles', alertStyles, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('badgeStyles', badgeStyles, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('bottomNavigationBarStyle', bottomNavigationBarStyle, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('buttonStyles', buttonStyles, level: DiagnosticLevel.debug))
Expand All @@ -209,6 +217,7 @@ final class FThemeData with Diagnosticable {
colorScheme == other.colorScheme &&
typography == other.typography &&
style == other.style &&
alertStyles == other.alertStyles &&
badgeStyles == other.badgeStyles &&
bottomNavigationBarStyle == other.bottomNavigationBarStyle &&
buttonStyles == other.buttonStyles &&
Expand All @@ -229,6 +238,7 @@ final class FThemeData with Diagnosticable {
colorScheme.hashCode ^
typography.hashCode ^
style.hashCode ^
alertStyles.hashCode ^
badgeStyles.hashCode ^
bottomNavigationBarStyle.hashCode ^
buttonStyles.hashCode ^
Expand Down
205 changes: 205 additions & 0 deletions forui/lib/src/widgets/alert/alert.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

import 'package:meta/meta.dart';

import 'package:forui/forui.dart';

part 'alert_styles.dart';

part 'alert_icon.dart';

/// An alert.
///
/// Displays a callout for user attention.
///
/// See:
/// * https://forui.dev/docs/alert for working examples.
/// * [FAlertStyle] for customizing an alert's appearance.
class FAlert extends StatelessWidget {
@useResult
static FAlertCustomStyle _of(BuildContext context) {
final theme = context.dependOnInheritedWidgetOfExactType<_InheritedData>();
return theme?.style ?? context.theme.alertStyles.primary;
}

/// The icon. Defaults to [FAssets.icons.circleAlert].
final Widget icon;

/// The title.
final Widget title;

/// The subtitle.
final Widget? subtitle;

/// The style. Defaults to [FAlertStyle.primary].
///
/// Although typically one of the pre-defined styles in [FAlertStyle], it can also be a [FAlertCustomStyle].
final FAlertStyle style;

/// Creates a [FAlert] with a tile, subtitle, and icon.
///
/// The alert's layout is as follows:
/// ```
/// |---------------------------|
/// | [icon] [title] |
/// | [subtitle] |
/// |---------------------------|
/// ```
FAlert({
required this.title,
Widget? icon,
this.subtitle,
this.style = FAlertStyle.primary,
super.key,
}) : icon = icon ?? FAlertIcon(icon: FAssets.icons.circleAlert);

@override
Widget build(BuildContext context) {
final style = switch (this.style) {
final FAlertCustomStyle style => style,
Variant.primary => context.theme.alertStyles.primary,
Variant.destructive => context.theme.alertStyles.destructive,
};

return DecoratedBox(
decoration: style.decoration,
child: Padding(
padding: style.padding,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
_InheritedData(style: style, child: icon),
Flexible(
child: Padding(
padding: const EdgeInsets.only(left: 8),
child: DefaultTextStyle.merge(
style: style.titleTextStyle,
child: title,
),
),
),
],
),
if (subtitle != null)
Row(
children: [
SizedBox(width: style.icon.height),
Flexible(
child: Padding(
padding: const EdgeInsets.only(top: 3, left: 8),
child: DefaultTextStyle.merge(
style: style.subtitleTextStyle,
child: subtitle!,
),
),
),
],
),
],
),
),
);
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty('style', style));
}
}

/// A [FAlert]'s style.
///
/// A style can be either one of the pre-defined styles in [FAlertStyle] or a [FAlertCustomStyle]. The pre-defined
/// styles are a convenient shorthand for the various [FAlertCustomStyle]s in the current context's [FAlertStyles].
sealed class FAlertStyle {
/// The alert's primary style.
///
/// Shorthand for the current context's [FAlertStyle.primary] style.
static const FAlertStyle primary = Variant.primary;

/// The alert's destructive style.
///
/// Shorthand for the current context's [FAlertStyle.destructive] style.
static const FAlertStyle destructive = Variant.destructive;
}

@internal
enum Variant implements FAlertStyle {
primary,
destructive,
}

/// A custom [FAlert] style.
final class FAlertCustomStyle extends FAlertStyle with Diagnosticable {
/// The decoration.
final BoxDecoration decoration;

/// The padding. Defaults to `EdgeInsets.fromLTRB(16, 12, 16, 16)`.
final EdgeInsets padding;

/// The icon's style.
final FAlertIconStyle icon;

/// The title's [TextStyle].
final TextStyle titleTextStyle;

/// The subtitle's [TextStyle].
final TextStyle subtitleTextStyle;

/// Creates a [FAlertCustomStyle].
FAlertCustomStyle({
required this.decoration,
required this.icon,
required this.titleTextStyle,
required this.subtitleTextStyle,
this.padding = const EdgeInsets.all(16),
});

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty('decoration', decoration))
..add(DiagnosticsProperty('padding', padding))
..add(DiagnosticsProperty('icon', icon))
..add(DiagnosticsProperty('titleTextStyle', titleTextStyle))
..add(DiagnosticsProperty('subtitleTextStyle', subtitleTextStyle));
}

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is FAlertCustomStyle &&
runtimeType == other.runtimeType &&
decoration == other.decoration &&
padding == other.padding &&
icon == other.icon &&
titleTextStyle == other.titleTextStyle &&
subtitleTextStyle == other.subtitleTextStyle;

@override
int get hashCode =>
decoration.hashCode ^ padding.hashCode ^ icon.hashCode ^ titleTextStyle.hashCode ^ subtitleTextStyle.hashCode;
}

class _InheritedData extends InheritedWidget {
final FAlertCustomStyle style;

const _InheritedData({
required this.style,
required super.child,
});

@override
bool updateShouldNotify(covariant _InheritedData old) => style != old.style;

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty('style', style));
}
}
Loading

0 comments on commit fb76077

Please sign in to comment.