Skip to content

Commit

Permalink
Refactor bottom navigation bar
Browse files Browse the repository at this point in the history
  • Loading branch information
Pante committed Aug 19, 2024
1 parent 5603754 commit 2af9254
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 42 deletions.
4 changes: 2 additions & 2 deletions docs/pages/docs/bottom-navigation-bar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ It is used to navigate between a small number of views, typically between three
Widget build(BuildContext context) => FBottomNavigationBar(
index: index,
onChange: (index) => setState(() => this.index = index),
items: [
children: [
FBottomNavigationBarItem(
icon: FAssets.icons.home,
label: 'Home',
Expand Down Expand Up @@ -72,7 +72,7 @@ It is used to navigate between a small number of views, typically between three
FBottomNavigationBar(
index: 0,
onChange: (index) => {},
items: [
children: [
FBottomNavigationBarItem(
icon: FAssets.icons.home,
label: 'Home',
Expand Down
8 changes: 7 additions & 1 deletion forui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

* Add `FButton.icon(...)`.

* Add `FBottomNavigationBar.of(...)`

* Add `FFormFieldStyle`.

* Add `FResizable.semanticFormatterCallback`.
Expand All @@ -16,6 +18,10 @@

* **Breaking:** Change `FAlertIconStyle.height` to `FAlertIconStyle.size`.

* **Breaking:** Rename `FBottomNavigationBar.items` to `FBottomNavigationBar.children`.

* **Breaking:** Remove `FBottomNavigationBar.raw(...)` - use the default constructor instead.

* Change `FResizable` to resize by `FResizable.resizePercentage` when using a keyboard.

* **Breaking:** Change `FResiableDividerStyle.thickness` to `FResizableDividerStyle.width`.
Expand All @@ -28,7 +34,7 @@

* **Breaking:** Change how `FTextFieldStyle` stores various state-dependent styles.

* **Breaking:** Remove `FTextField.error`.
* **Breaking:** Remove `FTextField.error` - use `FTextField.forceErrorText` instead.

### Fixes

Expand Down
2 changes: 1 addition & 1 deletion forui/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class _ApplicationState extends State<Application> {
footer: FBottomNavigationBar(
index: index,
onChange: (index) => setState(() => this.index = index),
items: [
children: [
FBottomNavigationBarItem(
icon: FAssets.icons.home,
label: 'Home',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

import 'package:collection/collection.dart';
import 'package:meta/meta.dart';

import 'package:forui/forui.dart';
Expand All @@ -15,16 +14,18 @@ import 'package:forui/src/foundation/tappable.dart';
/// See:
/// * https://forui.dev/docs/bottom-navigation-bar for working examples.
/// * [FBottomNavigationBarStyle] for customizing a bottom navigation bar's appearance.
/// * [FBottomNavigationBarItem] for the items in a bottom navigation bar.
class FBottomNavigationBar extends StatelessWidget {
/// Returns the [FBottomNavigationBarItemStyle] and currently selected index of the [FBottomNavigationBar] in the
/// given [context].
///
/// ## Contract
/// Throws [AssertionError] if there is no ancestor [FBottomNavigationBar] in the given [context].
static ({FBottomNavigationBarItemStyle itemStyle, bool current}) of(BuildContext context) {
final _InheritedData? result = context.dependOnInheritedWidgetOfExactType<_InheritedData>();
@useResult
static FBottomNavigationBarData of(BuildContext context) {
final result = context.dependOnInheritedWidgetOfExactType<FBottomNavigationBarData>();
assert(result != null, 'No _InheritedData found in context');
return (itemStyle: result!.itemStyle, current: result.current);
return result!;
}

/// The style.
Expand All @@ -34,19 +35,24 @@ class FBottomNavigationBar extends StatelessWidget {
final ValueChanged<int>? onChange;

/// The index.
///
/// ## Contract
/// Throws [AssertionError] if [index] is not null and is negative.
final int? index;

/// The children.
final List<Widget> children;

/// Creates a [FBottomNavigationBar] with [FBottomNavigationBarItem]s.
///
/// See [FBottomNavigationBarItem] for the items in a bottom navigation bar.
const FBottomNavigationBar({
required this.children,
this.style,
this.onChange,
this.index,
super.key,
});
}) : assert(index == null || 0 <= index, 'index must be null or non-negative.');

@override
Widget build(BuildContext context) {
Expand All @@ -69,9 +75,9 @@ class FBottomNavigationBar extends StatelessWidget {
onPress: () {
onChange?.call(i);
},
child: _InheritedData(
child: FBottomNavigationBarData(
itemStyle: style.itemStyle,
current: index == i,
selected: index == i,
child: child,
),
),
Expand All @@ -93,25 +99,30 @@ class FBottomNavigationBar extends StatelessWidget {
}
}

class _InheritedData extends InheritedWidget {
/// AFBottomNavigationBar]'s data.
class FBottomNavigationBarData extends InheritedWidget {
/// The item's style.
final FBottomNavigationBarItemStyle itemStyle;
final bool current;
/// Whether the item is currently selected.
final bool selected;

const _InheritedData({
/// Creates a [FBottomNavigationBarData].
const FBottomNavigationBarData({
required this.itemStyle,
required this.current,
required this.selected,
required super.child,
super.key,
});

@override
bool updateShouldNotify(_InheritedData old) => old.itemStyle != itemStyle || old.current != current;
bool updateShouldNotify(FBottomNavigationBarData old) => old.itemStyle != itemStyle || old.selected != selected;

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty('style', itemStyle))
..add(FlagProperty('current', value: current, ifTrue: 'current'));
..add(FlagProperty('selected', value: selected, ifTrue: 'selected'));
}
}

Expand Down Expand Up @@ -150,12 +161,12 @@ class FBottomNavigationBarStyle with Diagnosticable {
FBottomNavigationBarStyle copyWith({
BoxDecoration? decoration,
EdgeInsets? padding,
FBottomNavigationBarItemStyle? item,
FBottomNavigationBarItemStyle? itemStyle,
}) =>
FBottomNavigationBarStyle(
decoration: decoration ?? this.decoration,
padding: padding ?? this.padding,
itemStyle: item ?? this.itemStyle,
itemStyle: itemStyle ?? this.itemStyle,
);

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,36 @@ class FBottomNavigationBarItem extends StatelessWidget {

@override
Widget build(BuildContext context) {
final (:itemStyle, :current) = FBottomNavigationBar.of(context);
final FBottomNavigationBarData(:itemStyle, :selected) = FBottomNavigationBar.of(context);
final style = this.style ?? itemStyle;

return MouseRegion(
cursor: SystemMouseCursors.click,
child: Padding(
padding: style.padding,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
icon(
height: style.iconSize,
colorFilter: ColorFilter.mode(
current ? style.activeIconColor : style.inactiveIconColor,
BlendMode.srcIn,
return Semantics(
button: true,
selected: selected,
label: label,
excludeSemantics: true,
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Padding(
padding: style.padding,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
icon(
height: style.iconSize,
colorFilter: ColorFilter.mode(
selected ? style.activeIconColor : style.inactiveIconColor,
BlendMode.srcIn,
),
),
),
const SizedBox(height: 2),
Text(
label,
overflow: TextOverflow.ellipsis,
style: current ? style.activeTextStyle : style.inactiveTextStyle,
),
],
const SizedBox(height: 2),
Text(
label,
overflow: TextOverflow.ellipsis,
style: selected ? style.activeTextStyle : style.inactiveTextStyle,
),
],
),
),
),
);
Expand Down
2 changes: 1 addition & 1 deletion samples/lib/widgets/bottom_navigation_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class _DemoState extends State<_Demo> {
Widget build(BuildContext context) => FBottomNavigationBar(
index: index,
onChange: (index) => setState(() => this.index = index),
items: [
children: [
FBottomNavigationBarItem(
icon: FAssets.icons.home,
label: 'Home',
Expand Down
2 changes: 1 addition & 1 deletion samples/lib/widgets/scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class _DemoState extends State<_Demo> {
footer: FBottomNavigationBar(
index: index,
onChange: (index) => setState(() => this.index = index),
items: [
children: [
FBottomNavigationBarItem(
icon: FAssets.icons.home,
label: 'Home',
Expand Down

0 comments on commit 2af9254

Please sign in to comment.