Skip to content

Commit

Permalink
Styling done, Which fields should I add to tabStyle and which should …
Browse files Browse the repository at this point in the history
…i expose to the user
  • Loading branch information
Daviiddoo committed Jun 17, 2024
1 parent 071e395 commit 1f3e764
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 89 deletions.
34 changes: 31 additions & 3 deletions forui/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,39 @@ class ExampleWidget extends StatelessWidget {
),
const SizedBox(height: 10),
FTabs(
height: 35,
tabs: [
('Account', FTabContent(child: Column(children: [Container(color: Colors.red, height: 30,)],),)),
('Password', FTabContent(child: Column(children: [Container(color: Colors.blue, height: 30,)],),)),
MapEntry(
'Account',
FTabContent(
title: 'Account',
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
color: Colors.red,
height: 100,
),
],
),
),
),
MapEntry(
'Password',
FTabContent(
title: 'Password',
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
color: Colors.blue,
height: 100,
)
],
),
),
),
],

)
],
);
Expand Down
1 change: 0 additions & 1 deletion forui/lib/src/theme/theme_data.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:flutter/foundation.dart';

import 'package:forui/forui.dart';
import 'package:forui/src/widgets/tabs/tabs.dart';

/// The color scheme, fonts, overarching style, and widget specific styles used to configure child Forui widgets.
class FThemeData with Diagnosticable {
Expand Down
71 changes: 50 additions & 21 deletions forui/lib/src/widgets/tabs/tab_content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,30 @@ final class FTabContent extends StatelessWidget {
final String? title;
final String? subtitle;
final Widget? child;
final FCardContentStyle? style;
final FTabContentStyle? style;

const FTabContent({this.title, this.subtitle, this.child, this.style, super.key});
const FTabContent(
{this.title, this.subtitle, this.child, this.style, super.key});

@override
Widget build(BuildContext context) {
final font = context.theme.font;
final style = this.style ?? context.theme.cardStyle.content;
return Padding(
final style = this.style ?? context.theme.tabsStyle.content;
return Container(
decoration: style.decoration,
padding: style.padding,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (title != null) Text(title!, style: style.title.withFont(font)),
if (subtitle != null) Text(subtitle!, style: style.subtitle.withFont(font)),
if (subtitle != null)
Text(subtitle!, style: style.subtitle.withFont(font)),
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!,
),
],
Expand All @@ -41,6 +47,8 @@ final class FTabContent extends StatelessWidget {

/// A card content's style.
final class FTabContentStyle with Diagnosticable {
/// The decoration.
final BoxDecoration decoration;

/// The padding.
final EdgeInsets padding;
Expand All @@ -52,10 +60,17 @@ final class FTabContentStyle with Diagnosticable {
final TextStyle subtitle;

/// Creates a [FTabContentStyle].
const FTabContentStyle({required this.padding, required this.title, required this.subtitle});
const FTabContentStyle({
required this.decoration,
required this.padding,
required this.title,
required this.subtitle,
});

/// Creates a [FCardContentStyle] that inherits its properties from [colorScheme] and [font].
FTabContentStyle.inherit({required FColorScheme colorScheme, required FFont font}):
/// Creates a [FTabContentStyle] that inherits its properties from [colorScheme] and [font].
FTabContentStyle.inherit(
{required FColorScheme colorScheme, required FFont font,required FStyle style})
: decoration = BoxDecoration(borderRadius: style.borderRadius,border: Border.all(color: colorScheme.border)),
padding = const EdgeInsets.fromLTRB(16, 12, 16, 16),
title = TextStyle(
fontSize: font.base,
Expand All @@ -68,28 +83,42 @@ final class FTabContentStyle with Diagnosticable {
);

/// Creates a copy of this [FCardContentStyle] with the given properties replaced.
FTabContentStyle copyWith({EdgeInsets? padding, TextStyle? title, TextStyle? subtitle}) => FTabContentStyle(
padding: padding ?? this.padding,
title: title ?? this.title,
subtitle: subtitle ?? this.subtitle,
);
FTabContentStyle copyWith(
{BoxDecoration? decoration,
EdgeInsets? padding,
TextStyle? title,
TextStyle? subtitle}) =>
FTabContentStyle(
decoration: decoration ?? this.decoration,
padding: padding ?? this.padding,
title: title ?? this.title,
subtitle: subtitle ?? this.subtitle,
);

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty('padding', padding))
..add(DiagnosticsProperty('title', title))
..add(DiagnosticsProperty('subtitle', subtitle));
..add(DiagnosticsProperty('subtitle', subtitle))
..add(DiagnosticsProperty<BoxDecoration>('decoration', decoration));
}

@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 FTabContentStyle &&
runtimeType == other.runtimeType &&
decoration == other.decoration &&
padding == other.padding &&
title == other.title &&
subtitle == other.subtitle;

@override
int get hashCode => padding.hashCode ^ title.hashCode ^ subtitle.hashCode;
int get hashCode =>
decoration.hashCode ^
padding.hashCode ^
title.hashCode ^
subtitle.hashCode;
}
77 changes: 44 additions & 33 deletions forui/lib/src/widgets/tabs/tabs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ part 'tabs_style.dart';
part 'tab_content.dart';

/// A [FTabs] that allows switching between tabs.
class FTabs extends StatelessWidget {
class FTabs extends StatefulWidget {
/// The tab and it's corresponding view.
final List<(String, Widget)> tabs;
final List<MapEntry<String, Widget>> tabs;

/// The height of the tab button.
final double? height;
Expand All @@ -30,65 +30,76 @@ class FTabs extends StatelessWidget {
const FTabs({
required this.tabs,
this.height,
this.spacing = 2,
this.spacing = 10,
this.onTap,
this.initialIndex = 0,
this.style,
super.key,
});

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(IterableProperty<MapEntry<String, Widget>>('tabs', tabs))
..add(DoubleProperty('height', height))
..add(DiagnosticsProperty<double>('spacing', spacing))
..add(ObjectFlagProperty<ValueChanged<int>?>.has('onTap', onTap))
..add(IntProperty('initialIndex', initialIndex))
..add(DiagnosticsProperty<FTabsStyle?>('style', style));
}

@override
State<FTabs> createState() => _FTabsState();
}

class _FTabsState extends State<FTabs> with SingleTickerProviderStateMixin {
late int _selectedTab;

@override
void initState() {
super.initState();
_selectedTab = widget.initialIndex;
}

@override
Widget build(BuildContext context) {
final style = this.style ?? context.theme.tabsStyle;
final style = widget.style ?? context.theme.tabsStyle;
final tabs = widget.tabs;

return DefaultTabController(
initialIndex: initialIndex,
initialIndex: widget.initialIndex,
length: tabs.length,
child: Column(
children: [
DecoratedBox(
decoration: style.decoration,
child: TabBar(
indicatorSize: TabBarIndicatorSize.tab,
onTap: onTap,
padding: style.padding,
indicatorSize: style.indicatorSize,
indicator: style.indicator,
unselectedLabelStyle: style.unselectedLabel,
unselectedLabelColor: style.unselectedColor,
labelStyle: style.selectedLabel,
labelColor: style.selectedColor,
indicatorColor: Colors.transparent,
dividerColor: Colors.transparent,
indicator: style.indicator,
tabs: [
for (final (text, _) in tabs)
for (final child in tabs)
Tab(
height: height,
child: Text(text),
height: widget.height,
child: Text(child.key),
)
],
onTap: (index) {
setState(() {
_selectedTab = index;
});
widget.onTap?.call(_selectedTab);
},
),
),
SizedBox(height: spacing),
Flexible(
child: TabBarView(
physics: const BouncingScrollPhysics(),
children: [for (final (_, widget) in tabs) widget],
),
),
SizedBox(height: widget.spacing),
tabs[_selectedTab].value,
],
),
);
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(IterableProperty<(String, Widget)>('tabs', tabs))
..add(DoubleProperty('height', height))
..add(DiagnosticsProperty<double>('spacing', spacing))
..add(ObjectFlagProperty<ValueChanged<int>?>.has('onTap', onTap))
..add(IntProperty('initialIndex', initialIndex))
..add(DiagnosticsProperty<FTabsStyle?>('style', style));
}
}
Loading

0 comments on commit 1f3e764

Please sign in to comment.