creek
The AI Image Editor of 2030git clone https://github.com/maydayv7/creek
lib/ui/widgets/bottom_bar.dart (3649B)
1import 'dart:math';
2import 'package:flutter/material.dart';
3import 'package:flutter_svg/flutter_svg.dart';
4import 'package:creekui/ui/styles/variables.dart';
5import 'package:creekui/ui/pages/project_board_page.dart';
6import 'package:creekui/ui/pages/stylesheet_page.dart';
7import 'package:creekui/ui/pages/project_file_page.dart';
8
9enum BottomBarItem { moodboard, stylesheet, files }
10
11class BottomBar extends StatelessWidget {
12 final BottomBarItem currentTab;
13 final int projectId;
14
15 const BottomBar({
16 super.key,
17 required this.currentTab,
18 required this.projectId,
19 });
20
21 void _onTap(BuildContext context, BottomBarItem item) {
22 if (item == currentTab) return;
23
24 Widget nextPage;
25 switch (item) {
26 case BottomBarItem.moodboard:
27 nextPage = ProjectBoardPage(projectId: projectId);
28 break;
29 case BottomBarItem.stylesheet:
30 nextPage = StylesheetPage(projectId: projectId);
31 break;
32 case BottomBarItem.files:
33 nextPage = ProjectFilePage(projectId: projectId);
34 break;
35 }
36
37 Navigator.pushReplacement(
38 context,
39 PageRouteBuilder(
40 pageBuilder: (context, anim1, anim2) => nextPage,
41 transitionDuration: Duration.zero,
42 reverseTransitionDuration: Duration.zero,
43 ),
44 );
45 }
46
47 @override
48 Widget build(BuildContext context) {
49 // Safe Area Padding
50 final double safeBottom = MediaQuery.of(context).padding.bottom;
51 final double effectiveBottomPadding = max(safeBottom, 24.0);
52
53 return Container(
54 decoration: const BoxDecoration(
55 color: Variables.background,
56 border: Border(
57 top: BorderSide(color: Variables.borderSubtle, width: 1),
58 ),
59 ),
60 padding: EdgeInsets.only(bottom: effectiveBottomPadding, top: 12),
61 child: SizedBox(
62 height: 54,
63 child: Row(
64 children: [
65 Expanded(
66 child: _buildNavItem(
67 context,
68 BottomBarItem.moodboard,
69 "Moodboard",
70 "assets/icons/moodboard_icon.svg",
71 ),
72 ),
73 Expanded(
74 child: _buildNavItem(
75 context,
76 BottomBarItem.stylesheet,
77 "Stylesheet",
78 "assets/icons/stylesheet_icon.svg",
79 ),
80 ),
81 Expanded(
82 child: _buildNavItem(
83 context,
84 BottomBarItem.files,
85 "Files",
86 "assets/icons/files_icon.svg",
87 ),
88 ),
89 ],
90 ),
91 ),
92 );
93 }
94
95 Widget _buildNavItem(
96 BuildContext context,
97 BottomBarItem item,
98 String label,
99 String assetPath,
100 ) {
101 final bool isSelected = item == currentTab;
102 final Color color =
103 isSelected ? Variables.textPrimary : Variables.textDisabled;
104
105 return GestureDetector(
106 onTap: () => _onTap(context, item),
107 behavior: HitTestBehavior.opaque,
108 child: Center(
109 child: Column(
110 mainAxisAlignment: MainAxisAlignment.center,
111 children: [
112 SvgPicture.asset(
113 assetPath,
114 width: 24,
115 height: 24,
116 colorFilter: ColorFilter.mode(color, BlendMode.srcIn),
117 ),
118 const SizedBox(height: 6),
119 Text(
120 label,
121 style: Variables.captionStyle.copyWith(
122 color: color,
123 fontSize: 11,
124 fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
125 ),
126 ),
127 ],
128 ),
129 ),
130 );
131 }
132}