Skip to content

Commit 6004317

Browse files
committed
refactor: make the app bar more consistent
1 parent 73ede75 commit 6004317

6 files changed

Lines changed: 64 additions & 48 deletions

File tree

lib/features/productivity/productivity_insights_screen.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import 'package:flutter/material.dart';
1919
import 'package:flutter_riverpod/flutter_riverpod.dart';
2020
import 'package:lockin/features/productivity/productivity_provider.dart';
2121
import 'package:lockin/widgets/insight_tile.dart';
22+
import 'package:lockin/widgets/lockin_app_bar.dart';
2223

2324
class ProductivityInsightsScreen extends ConsumerWidget {
2425
const ProductivityInsightsScreen({super.key});
@@ -69,7 +70,7 @@ class ProductivityInsightsScreen extends ConsumerWidget {
6970
];
7071

7172
return Scaffold(
72-
appBar: AppBar(title: const Text('Productivity Insights')),
73+
appBar: const LockinAppBar(title: 'Productivity Insights'),
7374
body: ListView(
7475
padding: const EdgeInsets.all(16),
7576
children: entries

lib/features/recommendations/recommendations_page.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import 'package:lockin/features/habits/habit_category_provider.dart';
3030
import 'package:lockin/features/habits/habit_provider.dart';
3131
import 'package:lockin/features/settings/engagement_time_provider.dart';
3232
import 'package:lockin/features/tasks/task_provider.dart';
33+
import 'package:lockin/widgets/lockin_app_bar.dart';
3334
import 'package:lockin/widgets/recommendation_card.dart';
3435

3536
// Selected category for filtering recommendations. null == All
@@ -114,8 +115,9 @@ class RecommendationsPage extends ConsumerWidget {
114115
length: 3,
115116
initialIndex: initialTabIndex,
116117
child: Scaffold(
117-
appBar: AppBar(
118-
title: const Text('Recommendations'),
118+
appBar: LockinAppBar(
119+
title: 'Recommendations',
120+
actions: [],
119121
bottom: TabBar(
120122
tabs: const [
121123
Tab(text: 'Habits', icon: Icon(Icons.repeat)),
@@ -124,9 +126,7 @@ class RecommendationsPage extends ConsumerWidget {
124126
],
125127
indicatorColor: colorScheme.primary,
126128
indicatorSize: TabBarIndicatorSize.label,
127-
// Make the active label light (onSurface) so it contrasts with the dark background
128129
labelColor: colorScheme.onSurface,
129-
// Use a muted grey for unselected labels
130130
unselectedLabelColor: colorScheme.onSurfaceVariant,
131131
),
132132
),

lib/features/settings/settings_home.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import 'package:lockin/features/settings/backup_restore_util.dart';
3131
import 'package:lockin/features/settings/dynamic_color_provider.dart';
3232
import 'package:lockin/features/settings/engagement_time_provider.dart';
3333
import 'package:lockin/features/tasks/task_provider.dart';
34+
import 'package:lockin/widgets/lockin_app_bar.dart';
3435
import 'package:lockin/widgets/settings_item.dart';
3536
import 'package:permission_handler/permission_handler.dart';
3637

@@ -95,7 +96,7 @@ class _SettingsHomeState extends ConsumerState<SettingsHome> {
9596
final dynamicColorEnabled = ref.watch(dynamicColorEnabledProvider);
9697
final colorScheme = Theme.of(context).colorScheme;
9798
return Scaffold(
98-
appBar: AppBar(title: const Text('Settings'), elevation: 0),
99+
appBar: const LockinAppBar(title: 'Settings', actions: []),
99100
body: SafeArea(
100101
child: SingleChildScrollView(
101102
child: Padding(

lib/features/xp/xp_progression_screen.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import 'package:flutter/material.dart';
1919
import 'package:flutter_riverpod/flutter_riverpod.dart';
2020
import 'package:lockin/features/xp/xp_provider.dart';
21+
import 'package:lockin/widgets/lockin_app_bar.dart';
2122

2223
class XPProgressionScreen extends ConsumerWidget {
2324
const XPProgressionScreen({super.key});
@@ -41,7 +42,7 @@ class XPProgressionScreen extends ConsumerWidget {
4142
.where((w) => level >= (w['level'] as int))
4243
.toList();
4344
return Scaffold(
44-
appBar: AppBar(title: const Text('Progression Coaching')),
45+
appBar: const LockinAppBar(title: 'Progression Coaching'),
4546
body: ListView.builder(
4647
itemCount: unlockedWisdoms.length,
4748
itemBuilder: (context, index) {

lib/features/xp/xp_tab_screen.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
2020
import 'package:lockin/constants/app_constants.dart';
2121
import 'package:lockin/features/xp/xp_bar.dart';
2222
import 'package:lockin/features/xp/xp_rewards_screen.dart';
23+
import 'package:lockin/widgets/lockin_app_bar.dart';
2324

2425
class XPTabScreen extends ConsumerWidget {
2526
const XPTabScreen({super.key});
2627

2728
@override
2829
Widget build(BuildContext context, WidgetRef ref) {
2930
return Scaffold(
30-
appBar: AppBar(title: const Text('XP Dashboard')),
31+
appBar: const LockinAppBar(title: 'XP Dashboard'),
3132
body: SingleChildScrollView(
3233
padding: AppConstants.bodyPadding,
3334
child: Column(

lib/widgets/lockin_app_bar.dart

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,54 +18,66 @@
1818
import 'package:flutter/material.dart';
1919

2020
class LockinAppBar extends StatelessWidget implements PreferredSizeWidget {
21-
const LockinAppBar({required this.title, this.actions, super.key});
21+
const LockinAppBar({
22+
required this.title,
23+
this.actions,
24+
this.leading,
25+
this.bottom,
26+
this.centerTitle = false,
27+
this.elevation,
28+
this.backgroundColor,
29+
super.key,
30+
});
31+
2232
final String title;
2333
final List<Widget>? actions;
34+
final Widget? leading;
35+
final PreferredSizeWidget? bottom;
36+
final bool centerTitle;
37+
final double? elevation;
38+
final Color? backgroundColor;
39+
40+
static const List<Widget> _defaultActions = [_SettingsAction()];
2441

2542
@override
2643
Widget build(BuildContext context) {
27-
final defaultActions = [
28-
IconButton.filledTonal(
29-
icon: const Icon(Icons.settings),
30-
onPressed: () => Navigator.of(context).pushNamed('/settings'),
31-
),
32-
];
33-
return SafeArea(
34-
bottom: false,
35-
child: Column(
36-
mainAxisSize: MainAxisSize.min,
37-
children: [
38-
Flexible(
39-
child: Padding(
40-
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
41-
child: Row(
42-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
43-
children: [
44-
Expanded(
45-
child: Text(
46-
title,
47-
maxLines: 1,
48-
overflow: TextOverflow.ellipsis,
49-
style: Theme.of(
50-
context,
51-
).textTheme.headlineSmall?.copyWith(letterSpacing: 1.1),
52-
),
53-
),
54-
Row(
55-
mainAxisSize: MainAxisSize.min,
56-
children: actions ?? defaultActions,
57-
),
58-
],
59-
),
60-
),
61-
),
62-
// Subtle divider
63-
Container(height: 1, color: Colors.white.withValues(alpha: 0.08)),
64-
],
44+
final actionsList = actions ?? _defaultActions;
45+
46+
return AppBar(
47+
title: Text(
48+
title,
49+
style: Theme.of(
50+
context,
51+
).textTheme.headlineSmall?.copyWith(letterSpacing: 1.1),
6552
),
53+
actionsPadding: const EdgeInsets.symmetric(horizontal: 16),
54+
centerTitle: centerTitle,
55+
leading: leading,
56+
actions: actionsList,
57+
bottom: bottom,
58+
elevation: elevation,
59+
toolbarHeight: 64,
6660
);
6761
}
6862

6963
@override
70-
Size get preferredSize => const Size.fromHeight(64);
64+
Size get preferredSize {
65+
var height = 64.0;
66+
if (bottom != null) {
67+
height += bottom!.preferredSize.height;
68+
}
69+
return Size.fromHeight(height);
70+
}
71+
}
72+
73+
class _SettingsAction extends StatelessWidget {
74+
const _SettingsAction();
75+
76+
@override
77+
Widget build(BuildContext context) {
78+
return IconButton.filledTonal(
79+
icon: const Icon(Icons.settings),
80+
onPressed: () => Navigator.of(context).pushNamed('/settings'),
81+
);
82+
}
7183
}

0 commit comments

Comments
 (0)