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