Skip to content

Commit 09cf227

Browse files
authored
feat(app): apply liquid glass top bar to home screen (#35)
1 parent 0f113aa commit 09cf227

3 files changed

Lines changed: 120 additions & 47 deletions

File tree

app/lib/ui/home/home_screen.dart

Lines changed: 88 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,49 +26,112 @@ class HomeScreen extends ConsumerWidget {
2626
Widget build(BuildContext context, WidgetRef ref) {
2727
final repos = ref.watch(reposProvider).repos;
2828
final sessions = ref.watch(sessionsProvider);
29+
final cs = Theme.of(context).colorScheme;
30+
final topInset = MediaQuery.of(context).padding.top;
2931

3032
return Scaffold(
31-
appBar: AppBar(
32-
title: const Text('makit'),
33-
actions: [
34-
const ConnectionChip(),
35-
IconButton(
36-
icon: const Icon(Icons.create_new_folder_outlined),
37-
tooltip: 'Add repo',
38-
onPressed: () => showFolderBrowser(context),
33+
extendBodyBehindAppBar: true,
34+
extendBody: true,
35+
body: Stack(
36+
children: [
37+
RefreshIndicator(
38+
onRefresh: () =>
39+
ref.read(storeControllerProvider.notifier).refreshRepos(),
40+
child: repos.isEmpty
41+
? _EmptyState(
42+
onAdd: () => showFolderBrowser(context),
43+
topPadding: topInset + 60,
44+
)
45+
: ListView.builder(
46+
padding: EdgeInsets.fromLTRB(12, topInset + 60, 12, 24),
47+
itemCount: repos.length,
48+
itemBuilder: (context, i) => _RepoCard(
49+
repo: repos[i],
50+
sessions: sessions.forProject(repos[i].id),
51+
),
52+
),
3953
),
40-
IconButton(
41-
icon: const Icon(Icons.settings_outlined),
42-
onPressed: () => context.go('/settings'),
54+
Positioned(
55+
top: 0,
56+
left: 0,
57+
right: 0,
58+
child: IgnorePointer(
59+
child: Container(
60+
height: topInset + 96,
61+
decoration: BoxDecoration(
62+
gradient: LinearGradient(
63+
begin: Alignment.topCenter,
64+
end: Alignment.bottomCenter,
65+
colors: [
66+
cs.surface.withValues(alpha: 0.80),
67+
cs.surface.withValues(alpha: 0.70),
68+
cs.surface.withValues(alpha: 0),
69+
],
70+
stops: const [0, 0.5, 1],
71+
),
72+
),
73+
),
74+
),
4375
),
44-
],
45-
),
46-
body: RefreshIndicator(
47-
onRefresh: () =>
48-
ref.read(storeControllerProvider.notifier).refreshRepos(),
49-
child: repos.isEmpty
50-
? _EmptyState(onAdd: () => showFolderBrowser(context))
51-
: ListView.builder(
52-
padding: const EdgeInsets.fromLTRB(12, 12, 12, 24),
53-
itemCount: repos.length,
54-
itemBuilder: (context, i) => _RepoCard(
55-
repo: repos[i],
56-
sessions: sessions.forProject(repos[i].id),
76+
Positioned(
77+
top: 0,
78+
left: 0,
79+
right: 0,
80+
child: SafeArea(
81+
bottom: false,
82+
child: Padding(
83+
padding: const EdgeInsets.fromLTRB(12, 8, 12, 0),
84+
child: Row(
85+
children: [
86+
Expanded(
87+
child: Text(
88+
'makit',
89+
maxLines: 1,
90+
overflow: TextOverflow.ellipsis,
91+
style: Theme.of(context).textTheme.titleMedium
92+
?.copyWith(
93+
fontWeight: FontWeight.w600,
94+
shadows: [
95+
Shadow(color: cs.surface, blurRadius: 6),
96+
Shadow(color: cs.surface, blurRadius: 12),
97+
],
98+
),
99+
),
100+
),
101+
GlassCircleButton(
102+
icon: Icons.create_new_folder_outlined,
103+
tooltip: 'Add repo',
104+
onTap: () => showFolderBrowser(context),
105+
),
106+
const SizedBox(width: 6),
107+
GlassCircleButton(
108+
icon: Icons.settings_outlined,
109+
tooltip: 'Settings',
110+
onTap: () => context.go('/settings'),
111+
),
112+
const SizedBox(width: 6),
113+
const ConnectionChip(circular: true),
114+
],
57115
),
58116
),
117+
),
118+
),
119+
],
59120
),
60121
);
61122
}
62123
}
63124

64125
class _EmptyState extends StatelessWidget {
65-
const _EmptyState({required this.onAdd});
126+
const _EmptyState({required this.onAdd, required this.topPadding});
66127
final VoidCallback onAdd;
128+
final double topPadding;
67129

68130
@override
69131
Widget build(BuildContext context) {
70132
// Wrapped in a scroll view so RefreshIndicator still works when empty.
71133
return ListView(
134+
padding: EdgeInsets.only(top: topPadding),
72135
children: [
73136
SizedBox(height: MediaQuery.of(context).size.height * 0.18),
74137
Center(

app/lib/ui/session/session_screen.dart

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ class _SessionScreenState extends ConsumerState<SessionScreen> {
198198
padding: const EdgeInsets.fromLTRB(12, 8, 12, 0),
199199
child: Row(
200200
children: [
201-
_glassCircle(
201+
GlassCircleButton(
202202
icon: Icons.arrow_back,
203203
onTap: () => context.go('/'),
204204
),
@@ -294,27 +294,6 @@ class _SessionScreenState extends ConsumerState<SessionScreen> {
294294
}
295295
}
296296

297-
/// A round glass button for the top bar (back / toggle).
298-
Widget _glassCircle({
299-
required IconData icon,
300-
required VoidCallback onTap,
301-
String? tooltip,
302-
}) {
303-
return GlassSurface(
304-
borderRadius: 23,
305-
child: SizedBox(
306-
width: 46,
307-
height: 46,
308-
child: IconButton(
309-
tooltip: tooltip,
310-
padding: EdgeInsets.zero,
311-
icon: Icon(icon, size: 20),
312-
onPressed: onTap,
313-
),
314-
),
315-
);
316-
}
317-
318297
/// Glass overflow menu for the top bar — session-level actions (rename,
319298
/// quit). Mirrors the home screen's project overflow menu.
320299
Widget _glassMenu() {

app/lib/ui/widgets/glass.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,34 @@ class GlassSurface extends ConsumerWidget {
8181
);
8282
}
8383
}
84+
85+
/// Round glass icon button used in floating top bars (home, chat).
86+
class GlassCircleButton extends StatelessWidget {
87+
const GlassCircleButton({
88+
super.key,
89+
required this.icon,
90+
required this.onTap,
91+
this.tooltip,
92+
});
93+
94+
final IconData icon;
95+
final VoidCallback onTap;
96+
final String? tooltip;
97+
98+
@override
99+
Widget build(BuildContext context) {
100+
return GlassSurface(
101+
borderRadius: 23,
102+
child: SizedBox(
103+
width: 46,
104+
height: 46,
105+
child: IconButton(
106+
tooltip: tooltip,
107+
padding: EdgeInsets.zero,
108+
icon: Icon(icon, size: 20),
109+
onPressed: onTap,
110+
),
111+
),
112+
);
113+
}
114+
}

0 commit comments

Comments
 (0)