refactor(ui)!: remove bloc export in buttons to be state management solution agnostic (closes #147)
This commit is contained in:
+88
-44
@@ -15,14 +15,23 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
|
||||
import 'package:wyatt_ui_kit_example/theme/constants.dart';
|
||||
|
||||
class FileSelectionButtons extends StatelessWidget {
|
||||
class FileSelectionButtons extends StatefulWidget {
|
||||
const FileSelectionButtons({super.key});
|
||||
|
||||
@override
|
||||
State<FileSelectionButtons> createState() => _FileSelectionButtonsState();
|
||||
}
|
||||
|
||||
class _FileSelectionButtonsState extends State<FileSelectionButtons> {
|
||||
final _disabled = ValueNotifier(true);
|
||||
final _dynamic = ValueNotifier(false);
|
||||
|
||||
Widget _leading() => const DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: Constants.grey2,
|
||||
@@ -48,6 +57,7 @@ class FileSelectionButtons extends StatelessWidget {
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const Gap(20),
|
||||
// Default
|
||||
FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
@@ -56,65 +66,99 @@ class FileSelectionButtons extends StatelessWidget {
|
||||
subTitle: const TextWrapper('Taille max: 20 Mo'),
|
||||
),
|
||||
const Gap(20),
|
||||
FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Enabled',
|
||||
BlocProvider(
|
||||
create: (context) => InvalidButtonCubit()..freeze(),
|
||||
child: FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Enabled',
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
)
|
||||
..bloc.enable()
|
||||
..bloc.freeze(),
|
||||
),
|
||||
const Gap(20),
|
||||
// Using a ValueNotifier to disable the button
|
||||
FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Disabled',
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
)
|
||||
..bloc.disable()
|
||||
..bloc.freeze(),
|
||||
disabled: _disabled,
|
||||
),
|
||||
const Gap(20),
|
||||
FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Hovered',
|
||||
BlocProvider(
|
||||
create: (context) => InvalidButtonCubit()..hover(),
|
||||
child: FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Hovered',
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
)
|
||||
..bloc.onMouseEnter()
|
||||
..bloc.freeze(),
|
||||
),
|
||||
const Gap(20),
|
||||
FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Focused',
|
||||
BlocProvider(
|
||||
create: (context) => InvalidButtonCubit()..focus(),
|
||||
child: FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Focused',
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
)
|
||||
..bloc.onFocus()
|
||||
..bloc.freeze(),
|
||||
),
|
||||
const Gap(20),
|
||||
FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Tapped',
|
||||
BlocProvider(
|
||||
create: (context) => InvalidButtonCubit()..tap(),
|
||||
child: FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Tapped',
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
)
|
||||
..bloc.onClickDown()
|
||||
..bloc.freeze(),
|
||||
),
|
||||
const Gap(20),
|
||||
FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Invalid',
|
||||
BlocProvider(
|
||||
create: (context) => InvalidButtonCubit()..invalidate(),
|
||||
child: FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Invalid',
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
)
|
||||
..bloc.invalidate()
|
||||
..bloc.freeze(),
|
||||
),
|
||||
const Gap(20),
|
||||
// Dynamic, disabled with ValueNotifier and invalid with BlocProvider.
|
||||
// Keep the state when the button is disabled.
|
||||
Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text('Enabled'),
|
||||
Checkbox(
|
||||
value: !_dynamic.value,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_dynamic.value = !_dynamic.value;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
FileSelectionButton(
|
||||
leading: _leading(),
|
||||
title: const TextWrapper(
|
||||
'Dynamic',
|
||||
),
|
||||
subTitle: const TextWrapper('Subtitle'),
|
||||
disabled: _dynamic,
|
||||
),
|
||||
],
|
||||
),
|
||||
const Gap(20),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -15,13 +15,22 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
|
||||
|
||||
class FlatButtons extends StatelessWidget {
|
||||
class FlatButtons extends StatefulWidget {
|
||||
const FlatButtons({super.key});
|
||||
|
||||
@override
|
||||
State<FlatButtons> createState() => _FlatButtonsState();
|
||||
}
|
||||
|
||||
class _FlatButtonsState extends State<FlatButtons> {
|
||||
final _disabled = ValueNotifier(true);
|
||||
final _dynamic = ValueNotifier(false);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Column(
|
||||
children: [
|
||||
@@ -30,56 +39,80 @@ class FlatButtons extends StatelessWidget {
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const Gap(20),
|
||||
Center(
|
||||
// Default
|
||||
const Center(
|
||||
/// You can overwrite global textstyle of the label with [label],
|
||||
/// but if you only want to override the color/gradient of the text
|
||||
/// in a particular case you can override the style that will
|
||||
/// be merge during the build.
|
||||
child: FlatButton(
|
||||
label: const TextWrapper(
|
||||
label: TextWrapper(
|
||||
'Voir notre savoir faire',
|
||||
),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
Center(
|
||||
child: FlatButton(
|
||||
label: const TextWrapper('Enabled'),
|
||||
)
|
||||
..bloc.enable()
|
||||
..bloc.freeze(),
|
||||
child: BlocProvider(
|
||||
create: (context) => ButtonCubit()..freeze(),
|
||||
child: const FlatButton(
|
||||
label: TextWrapper('Enabled'),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
// Disabled with ValueNotifier
|
||||
Center(
|
||||
child: FlatButton(
|
||||
label: const TextWrapper('Disabled'),
|
||||
)
|
||||
..bloc.disable()
|
||||
..bloc.freeze(),
|
||||
disabled: _disabled,
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
Center(
|
||||
child: FlatButton(
|
||||
label: const TextWrapper('Hovered'),
|
||||
)
|
||||
..bloc.onMouseEnter()
|
||||
..bloc.freeze(),
|
||||
child: BlocProvider(
|
||||
create: (context) => ButtonCubit()..hover(),
|
||||
child: const FlatButton(
|
||||
label: TextWrapper('Hovered'),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
Center(
|
||||
child: FlatButton(
|
||||
label: const TextWrapper('Focused'),
|
||||
)
|
||||
..bloc.onFocus()
|
||||
..bloc.freeze(),
|
||||
child: BlocProvider(
|
||||
create: (context) => ButtonCubit()..focus(),
|
||||
child: const FlatButton(
|
||||
label: TextWrapper('Focused'),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
Center(
|
||||
child: FlatButton(
|
||||
label: const TextWrapper('Tapped'),
|
||||
)
|
||||
..bloc.onClickDown()
|
||||
..bloc.freeze(),
|
||||
child: BlocProvider(
|
||||
create: (context) => ButtonCubit()..tap(),
|
||||
child: const FlatButton(
|
||||
label: TextWrapper('Tapped'),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
// Dynamic, disabled with ValueNotifier and
|
||||
// keep the state when the button is disabled
|
||||
Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: !_dynamic.value,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_dynamic.value = !_dynamic.value;
|
||||
});
|
||||
},
|
||||
),
|
||||
FlatButton(
|
||||
label: const TextWrapper('Dynamic'),
|
||||
disabled: _dynamic,
|
||||
),
|
||||
],
|
||||
),
|
||||
const Gap(20),
|
||||
],
|
||||
|
||||
+74
-34
@@ -15,12 +15,21 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
|
||||
|
||||
class SimpleIconButtons extends StatelessWidget {
|
||||
class SimpleIconButtons extends StatefulWidget {
|
||||
const SimpleIconButtons({super.key});
|
||||
|
||||
@override
|
||||
State<SimpleIconButtons> createState() => _SimpleIconButtonsState();
|
||||
}
|
||||
|
||||
class _SimpleIconButtonsState extends State<SimpleIconButtons> {
|
||||
final _disabled = ValueNotifier(true);
|
||||
final _dynamic = ValueNotifier(false);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -30,8 +39,9 @@ class SimpleIconButtons extends StatelessWidget {
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const Gap(20),
|
||||
SimpleIconButton(
|
||||
icon: const Icon(
|
||||
// Default
|
||||
const SimpleIconButton(
|
||||
icon: Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
),
|
||||
@@ -42,71 +52,101 @@ class SimpleIconButtons extends StatelessWidget {
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
const Gap(10),
|
||||
SimpleIconButton(
|
||||
icon: const Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
BlocProvider(
|
||||
create: (context) => ButtonCubit()..freeze(),
|
||||
child: const SimpleIconButton(
|
||||
icon: Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
),
|
||||
),
|
||||
)
|
||||
..bloc.enable()
|
||||
..bloc.freeze(),
|
||||
),
|
||||
const Gap(20),
|
||||
Text(
|
||||
'Disabled',
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
const Gap(10),
|
||||
// Disabled using ValueNotifier
|
||||
SimpleIconButton(
|
||||
icon: const Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
),
|
||||
)
|
||||
..bloc.disable()
|
||||
..bloc.freeze(),
|
||||
disabled: _disabled,
|
||||
),
|
||||
const Gap(20),
|
||||
Text(
|
||||
'Hovered',
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
const Gap(10),
|
||||
SimpleIconButton(
|
||||
icon: const Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
BlocProvider(
|
||||
create: (context) => ButtonCubit()..hover(),
|
||||
child: const SimpleIconButton(
|
||||
icon: Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
),
|
||||
),
|
||||
)
|
||||
..bloc.onMouseEnter()
|
||||
..bloc.freeze(),
|
||||
),
|
||||
const Gap(20),
|
||||
Text(
|
||||
'Focused',
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
const Gap(10),
|
||||
SimpleIconButton(
|
||||
icon: const Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
BlocProvider(
|
||||
create: (context) => ButtonCubit()..focus(),
|
||||
child: const SimpleIconButton(
|
||||
icon: Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
),
|
||||
),
|
||||
)
|
||||
..bloc.onFocus()
|
||||
..bloc.freeze(),
|
||||
),
|
||||
const Gap(20),
|
||||
Text(
|
||||
'Tapped',
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
const Gap(10),
|
||||
SimpleIconButton(
|
||||
icon: const Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
BlocProvider(
|
||||
create: (context) => ButtonCubit()..tap(),
|
||||
child: const SimpleIconButton(
|
||||
icon: Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
),
|
||||
),
|
||||
)
|
||||
..bloc.onClickDown()
|
||||
..bloc.freeze(),
|
||||
),
|
||||
const Gap(20),
|
||||
Text(
|
||||
'Dynamic',
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
const Gap(10),
|
||||
// Dynamic, disabled with ValueNotifier and
|
||||
// keep the state when the button is disabled
|
||||
Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: !_dynamic.value,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_dynamic.value = !_dynamic.value;
|
||||
});
|
||||
},
|
||||
),
|
||||
SimpleIconButton(
|
||||
icon: const Icon(
|
||||
Icons.storm_outlined,
|
||||
size: 17,
|
||||
),
|
||||
disabled: _dynamic,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,14 +15,23 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
|
||||
import 'package:wyatt_ui_kit_example/theme/constants.dart';
|
||||
|
||||
class SymbolButtons extends StatelessWidget {
|
||||
class SymbolButtons extends StatefulWidget {
|
||||
const SymbolButtons({super.key});
|
||||
|
||||
@override
|
||||
State<SymbolButtons> createState() => _SymbolButtonsState();
|
||||
}
|
||||
|
||||
class _SymbolButtonsState extends State<SymbolButtons> {
|
||||
final _disabled = ValueNotifier(true);
|
||||
final _dynamic = ValueNotifier(false);
|
||||
|
||||
Icon _icon(BuildContext context) => Icon(
|
||||
Icons.android,
|
||||
size: 25,
|
||||
@@ -45,47 +54,70 @@ class SymbolButtons extends StatelessWidget {
|
||||
icon: _icon(context),
|
||||
),
|
||||
const Gap(20),
|
||||
SymbolButton(
|
||||
label: const TextWrapper('Enabled'),
|
||||
icon: _icon(context),
|
||||
)
|
||||
..bloc.enable()
|
||||
..bloc.freeze(),
|
||||
BlocProvider(
|
||||
create: (context) => SelectableButtonCubit()..freeze(),
|
||||
child: SymbolButton(
|
||||
label: const TextWrapper('Enabled'),
|
||||
icon: _icon(context),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
// Disabled
|
||||
SymbolButton(
|
||||
label: const TextWrapper('Disabled'),
|
||||
icon: _icon(context),
|
||||
)
|
||||
..bloc.disable()
|
||||
..bloc.freeze(),
|
||||
disabled: _disabled,
|
||||
),
|
||||
const Gap(20),
|
||||
SymbolButton(
|
||||
label: const TextWrapper('Hovered'),
|
||||
icon: _icon(context),
|
||||
)
|
||||
..bloc.onMouseEnter()
|
||||
..bloc.freeze(),
|
||||
BlocProvider(
|
||||
create: (context) => SelectableButtonCubit()..hover(),
|
||||
child: SymbolButton(
|
||||
label: const TextWrapper('Hovered'),
|
||||
icon: _icon(context),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
SymbolButton(
|
||||
label: const TextWrapper('Focused'),
|
||||
icon: _icon(context),
|
||||
)
|
||||
..bloc.onFocus()
|
||||
..bloc.freeze(),
|
||||
BlocProvider(
|
||||
create: (context) => SelectableButtonCubit()..focus(),
|
||||
child: SymbolButton(
|
||||
label: const TextWrapper('Focused'),
|
||||
icon: _icon(context),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
SymbolButton(
|
||||
label: const TextWrapper('Tapped'),
|
||||
icon: _icon(context),
|
||||
)
|
||||
..bloc.onClickDown()
|
||||
..bloc.freeze(),
|
||||
BlocProvider(
|
||||
create: (context) => SelectableButtonCubit()..tap(),
|
||||
child: SymbolButton(
|
||||
label: const TextWrapper('Tapped'),
|
||||
icon: _icon(context),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
SymbolButton(
|
||||
label: const TextWrapper('Selected'),
|
||||
icon: _icon(context),
|
||||
)
|
||||
..bloc.select()
|
||||
..bloc.freeze(),
|
||||
BlocProvider(
|
||||
create: (context) => SelectableButtonCubit()..select(),
|
||||
child: SymbolButton(
|
||||
label: const TextWrapper('Selected'),
|
||||
icon: _icon(context),
|
||||
),
|
||||
),
|
||||
const Gap(20),
|
||||
Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: !_dynamic.value,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_dynamic.value = !_dynamic.value;
|
||||
});
|
||||
},
|
||||
),
|
||||
SymbolButton(
|
||||
label: const TextWrapper('Dynamic'),
|
||||
icon: _icon(context),
|
||||
disabled: _dynamic,
|
||||
),
|
||||
],
|
||||
),
|
||||
const Gap(20),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
|
||||
Reference in New Issue
Block a user