Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate switches with forms #74

Merged
merged 7 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions docs/pages/docs/checkbox.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ On touch devices, it is recommended to use a [switch](/docs/switch) instead in m

<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='checkbox' query={{enabled: "true"}}/>
<Widget name='checkbox' query={{enabled: 'true'}}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
Expand All @@ -25,6 +25,8 @@ On touch devices, it is recommended to use a [switch](/docs/switch) instead in m
FCheckbox(
enabled: true,
initialValue: true,
autofocus: true,
onChanged: (value) {},
);
```

Expand All @@ -33,25 +35,25 @@ FCheckbox(
### Disabled

<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='checkbox' query={{enabled: "false"}}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
FCheckbox(
enabled: false,
);
```
</Tabs.Tab>
<Tabs.Tab>
<Widget name='checkbox' query={{enabled: 'false'}}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
FCheckbox(
enabled: false,
);
```
</Tabs.Tab>
</Tabs>

### Form

<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='checkbox' variant='form' query={{enabled: "true"}}/>
</Tabs.Tab>
<Tabs.Tab>
<Tabs.Tab>
<Widget name='checkbox' variant='form' query={{enabled: 'true'}}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
class LoginForm extends StatefulWidget {
const LoginForm({super.key});
Expand Down Expand Up @@ -96,12 +98,17 @@ FCheckbox(
const SizedBox(height: 30),
FButton(
label: const Text('Login'),
onPress: () => _formKey.currentState!.validate(),
onPress: () {
if (!_formKey.currentState!.validate()) {
// Handle errors here.
return;
}
},
),
],
),
);
}
```
</Tabs.Tab>
</Tabs>
</Tabs.Tab>
</Tabs>
100 changes: 88 additions & 12 deletions docs/pages/docs/switch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,15 @@ import { Tabs } from 'nextra/components';
import { Widget } from "../../components/widget";

# Switch
A switch that allows the user to toggle between checked and unchecked.
A switch that allows the user to toggle between checked and unchecked. It can also be used in a form.

<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='switch' query={{}}/>
<Widget name='switch' query={{enabled: 'true'}}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
final notifier = ValueNotifier(false);

ValueListenableBuilder(
valueListenable: notifier,
builder: (context, value, __) => FSwitch(
value: value,
onChanged: (value) => notifier.value = value,
),
);
FSwitch();
```
</Tabs.Tab>
</Tabs>
Expand All @@ -29,8 +21,92 @@ A switch that allows the user to toggle between checked and unchecked.

```dart
FSwitch(
value: true,
enabled: true,
initialValue: true,
autofocus: true,
onChanged: (value) {},
);
```

## Examples

### Disabled

<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='switch' query={{enabled: 'false'}}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
FSwitch(
enabled: false,
);
```
</Tabs.Tab>
</Tabs>

### Form

<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='switch' variant='form' query={{}} height={550}/>
</Tabs.Tab>
<Tabs.Tab>
```dart
class LoginForm extends StatefulWidget {
const LoginForm({super.key});

@override
State<LoginForm> createState() => _LoginFormState();
}

class _LoginFormState extends State<LoginForm> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) => Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FTextField.email(
hint: '[email protected]',
help: const Text(''),
validator: (value) => (value?.contains('@') ?? false) ? null : 'Please enter a valid email.',
),
const SizedBox(height: 4),
FTextField.password(
hint: '',
help: const Text(''),
validator: (value) => 8 <= (value?.length ?? 0) ? null : 'Password must be at least 8 characters long.',
),
const SizedBox(height: 4),
Row(
children: [
const FSwitch(),
const SizedBox(width: 7),
Text('Remember password?', style: context.theme.typography.sm),
],
),
const SizedBox(height: 30),
FButton(
label: const Text('Login'),
onPress: () => {
if (!_formKey.currentState!.validate()) {
// Handle errors here.
return;
}
},
),
],
),
);
}
```
</Tabs.Tab>
</Tabs>
2 changes: 1 addition & 1 deletion docs/pages/docs/text-field.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ FTextField.multiline(

<Tabs items={['Preview', 'Code']}>
<Tabs.Tab>
<Widget name='text-field' variant='form' query={{}}/>
<Widget name='text-field' variant='form' height={550} query={{}} height={550}/>
Pante marked this conversation as resolved.
Show resolved Hide resolved
</Tabs.Tab>
<Tabs.Tab>
```dart
Expand Down
10 changes: 10 additions & 0 deletions forui/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## Next

### Enhancements
* **Breaking** Change `FSwitch` to be usable in `Form`s.
Pante marked this conversation as resolved.
Show resolved Hide resolved
* **Breaking** Rename `FThemeData.checkBoxStyle` to `FThemeData.checkboxStyle` for consistency.

### Fixes
* Fix missing `style` parameter for `FCheckbox`.


## 0.2.0+3

### Fixes
Expand Down
2 changes: 1 addition & 1 deletion forui/example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.1.0"
version: "0.2.0+3"
forui_assets:
dependency: "direct overridden"
description:
Expand Down
16 changes: 8 additions & 8 deletions forui/lib/src/theme/theme_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ final class FThemeData with Diagnosticable {
final FCardStyle cardStyle;

/// The checkbox style.
final FCheckboxStyle checkBoxStyle;
final FCheckboxStyle checkboxStyle;

/// The dialog style.
final FDialogStyle dialogStyle;
Expand Down Expand Up @@ -72,7 +72,7 @@ final class FThemeData with Diagnosticable {
required this.badgeStyles,
required this.buttonStyles,
required this.cardStyle,
required this.checkBoxStyle,
required this.checkboxStyle,
required this.dialogStyle,
required this.headerStyle,
required this.progressStyle,
Expand Down Expand Up @@ -100,7 +100,7 @@ final class FThemeData with Diagnosticable {
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),
checkBoxStyle: FCheckboxStyle.inherit(colorScheme: colorScheme),
checkboxStyle: FCheckboxStyle.inherit(colorScheme: colorScheme),
dialogStyle: FDialogStyle.inherit(colorScheme: colorScheme, typography: typography, style: style),
headerStyle: FHeaderStyles.inherit(colorScheme: colorScheme, typography: typography, style: style),
progressStyle: FProgressStyle.inherit(colorScheme: colorScheme, style: style),
Expand Down Expand Up @@ -136,7 +136,7 @@ final class FThemeData with Diagnosticable {
FBadgeStyles? badgeStyles,
FButtonStyles? buttonStyles,
FCardStyle? cardStyle,
FCheckboxStyle? checkBoxStyle,
FCheckboxStyle? checkboxStyle,
FDialogStyle? dialogStyle,
FHeaderStyles? headerStyle,
FProgressStyle? progressStyle,
Expand All @@ -153,7 +153,7 @@ final class FThemeData with Diagnosticable {
badgeStyles: badgeStyles ?? this.badgeStyles,
buttonStyles: buttonStyles ?? this.buttonStyles,
cardStyle: cardStyle ?? this.cardStyle,
checkBoxStyle: checkBoxStyle ?? this.checkBoxStyle,
checkboxStyle: checkboxStyle ?? this.checkboxStyle,
dialogStyle: dialogStyle ?? this.dialogStyle,
headerStyle: headerStyle ?? this.headerStyle,
progressStyle: progressStyle ?? this.progressStyle,
Expand All @@ -174,7 +174,7 @@ final class FThemeData with Diagnosticable {
..add(DiagnosticsProperty('badgeStyles', badgeStyles, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('buttonStyles', buttonStyles, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('cardStyle', cardStyle, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('checkBoxStyle', checkBoxStyle, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('checkboxStyle', checkboxStyle, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('dialogStyle', dialogStyle, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('headerStyle', headerStyle, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('progressStyle', progressStyle))
Expand All @@ -196,7 +196,7 @@ final class FThemeData with Diagnosticable {
badgeStyles == other.badgeStyles &&
buttonStyles == other.buttonStyles &&
cardStyle == other.cardStyle &&
checkBoxStyle == other.checkBoxStyle &&
checkboxStyle == other.checkboxStyle &&
dialogStyle == other.dialogStyle &&
headerStyle == other.headerStyle &&
progressStyle == other.progressStyle &&
Expand All @@ -214,7 +214,7 @@ final class FThemeData with Diagnosticable {
badgeStyles.hashCode ^
buttonStyles.hashCode ^
cardStyle.hashCode ^
checkBoxStyle.hashCode ^
checkboxStyle.hashCode ^
dialogStyle.hashCode ^
headerStyle.hashCode ^
progressStyle.hashCode ^
Expand Down
1 change: 1 addition & 0 deletions forui/lib/src/widgets/calendar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
final class _Day {}
31 changes: 16 additions & 15 deletions forui/lib/src/widgets/checkbox.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/semantics.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';

import 'package:forui/forui.dart';

/// A checkbox control that allows the user to toggle between checked and not checked.
///
/// On touch devices, it is recommended to use a [FSwitch] instead in most cases. A [FCheckbox] is internally a
/// [FormField], therefore it can be used in a form.
/// A [FCheckbox] is internally a [FormField], therefore it can be used in a form.
///
/// On touch devices, it is recommended to use a [FSwitch] instead of a [FCheckbox] in most cases.
///
/// See:
/// * https://forui.dev/docs/checkbox for working examples.
/// * [FCheckboxStyle] for customizing a checkbox's appearance.
class FCheckbox extends StatelessWidget {
/// The semantic label of the dialog used by accessibility frameworks to announce screen transitions when the dialog
/// is opened and closed.
///
/// See also:
/// * [SemanticsConfiguration.namesRoute], for a description of how this value is used.
/// The style. Defaults to [FThemeData.checkboxStyle].
final FCheckboxStyle? style;

/// The semantic label of the checkbox used by accessibility frameworks.
final String? semanticLabel;

/// Called when the user initiates a change to the FCheckBox's value: when they have checked or unchecked this box.
Expand All @@ -44,27 +43,27 @@ class FCheckbox extends StatelessWidget {
/// The returned value is exposed by the [FormFieldState.errorText] property.
final FormFieldValidator<bool>? validator;

/// An optional value to initialize the form field to, or null otherwise.
/// An optional value to initialize the checkbox. Defaults to false.
final bool initialValue;

/// Whether the form is able to receive user input.
///
/// Defaults to true. If [autovalidateMode] is not [AutovalidateMode.disabled], the field will be auto validated.
/// Defaults to true. If [autovalidateMode] is not [AutovalidateMode.disabled], the checkbox will be auto validated.
/// Likewise, if this field is false, the widget will not be validated regardless of [autovalidateMode].
final bool enabled;

/// Used to enable/disable this form field auto validation and update its error text.
/// Used to enable/disable this checkbox auto validation and update its error text.
///
/// Defaults to [AutovalidateMode.disabled].
///
/// If [AutovalidateMode.onUserInteraction], this FormField will only auto-validate after its content changes. If
/// If [AutovalidateMode.onUserInteraction], this checkbox will only auto-validate after its content changes. If
/// [AutovalidateMode.always], it will auto-validate even without user interaction. If [AutovalidateMode.disabled],
/// auto-validation will be disabled.
final AutovalidateMode? autovalidateMode;

/// Restoration ID to save and restore the state of the form field.
/// Restoration ID to save and restore the state of the checkbox.
///
/// Setting the restoration ID to a non-null value results in whether or not the form field validation persists.
/// Setting the restoration ID to a non-null value results in whether or not the checkbox validation persists.
///
/// The state of this widget is persisted in a [RestorationBucket] claimed from the surrounding [RestorationScope]
/// using the provided restoration ID.
Expand All @@ -75,6 +74,7 @@ class FCheckbox extends StatelessWidget {

/// Creates a [FCheckbox].
const FCheckbox({
this.style,
this.semanticLabel,
this.onChange,
this.autofocus = false,
Expand All @@ -91,7 +91,7 @@ class FCheckbox extends StatelessWidget {

@override
Widget build(BuildContext context) {
final style = context.theme.checkBoxStyle;
final style = this.style ?? context.theme.checkboxStyle;
final stateStyle = enabled ? style.enabledStyle : style.disabledStyle;

return FocusableActionDetector(
Expand Down Expand Up @@ -160,6 +160,7 @@ class FCheckbox extends StatelessWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty('style', style))
..add(StringProperty('semanticLabel', semanticLabel))
..add(ObjectFlagProperty.has('onChange', onChange))
..add(DiagnosticsProperty('autofocus', autofocus))
Expand Down
Loading
Loading