import 'dart:ui' show ImageFilter; import 'package:flutter/material.dart'; import 'devices_screen.dart'; import 'timbang_screen.dart'; /// Root scaffold with bottom nav: Devices and Timbang (scale display). class MainShell extends StatefulWidget { const MainShell({super.key}); @override State createState() => _MainShellState(); } class _MainShellState extends State { int _index = 0; static const _tabs = [ (label: 'Devices', icon: Icons.list_alt), (label: 'Timbang', icon: Icons.monitor_weight), ]; @override Widget build(BuildContext context) { return Scaffold( extendBody: true, body: IndexedStack( index: _index, children: const [ DevicesScreen(), TimbangScreen(), ], ), bottomNavigationBar: _FloatingGlassNavigationBar( currentIndex: _index, tabs: _tabs, onTap: (i) => setState(() => _index = i), ), ); } } class _FloatingGlassNavigationBar extends StatelessWidget { const _FloatingGlassNavigationBar({ required this.currentIndex, required this.tabs, required this.onTap, }); final int currentIndex; final List<({String label, IconData icon})> tabs; final ValueChanged onTap; @override Widget build(BuildContext context) { return SafeArea( minimum: const EdgeInsets.fromLTRB(20, 0, 20, 18), child: ClipRRect( borderRadius: BorderRadius.circular(32), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 24, sigmaY: 24), child: Container( height: 72, padding: const EdgeInsets.all(8), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Colors.white.withValues(alpha: 0.84), Colors.white.withValues(alpha: 0.62), ], ), borderRadius: BorderRadius.circular(32), border: Border.all(color: Colors.white.withValues(alpha: 0.9)), boxShadow: [ BoxShadow( color: const Color(0xFF0F172A).withValues(alpha: 0.13), blurRadius: 34, offset: const Offset(0, 18), ), BoxShadow( color: const Color(0xFF38BDF8).withValues(alpha: 0.1), blurRadius: 24, offset: const Offset(0, -6), ), ], ), child: Row( children: [ for (var i = 0; i < tabs.length; i++) Expanded( child: _GlassNavigationItem( icon: tabs[i].icon, label: tabs[i].label, isSelected: i == currentIndex, onTap: () => onTap(i), ), ), ], ), ), ), ), ); } } class _GlassNavigationItem extends StatelessWidget { const _GlassNavigationItem({ required this.icon, required this.label, required this.isSelected, required this.onTap, }); final IconData icon; final String label; final bool isSelected; final VoidCallback onTap; @override Widget build(BuildContext context) { const activeColor = Color(0xFF2563EB); const inactiveColor = Color(0xFF64748B); return Material( color: Colors.transparent, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(26), child: AnimatedContainer( duration: const Duration(milliseconds: 220), curve: Curves.easeOutCubic, alignment: Alignment.center, margin: const EdgeInsets.symmetric(horizontal: 2), padding: const EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( gradient: isSelected ? LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Colors.white.withValues(alpha: 0.95), activeColor.withValues(alpha: 0.12), ], ) : null, color: isSelected ? null : Colors.transparent, borderRadius: BorderRadius.circular(26), border: Border.all( color: isSelected ? Colors.white.withValues(alpha: 0.96) : Colors.transparent, ), boxShadow: isSelected ? [ BoxShadow( color: activeColor.withValues(alpha: 0.16), blurRadius: 18, offset: const Offset(0, 8), ), ] : null, ), child: AnimatedScale( duration: const Duration(milliseconds: 180), curve: Curves.easeOutCubic, scale: isSelected ? 1 : 0.96, child: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ Icon( icon, color: isSelected ? activeColor : inactiveColor, size: 22, ), AnimatedSize( duration: const Duration(milliseconds: 220), curve: Curves.easeOutCubic, child: isSelected ? Row( children: [ const SizedBox(width: 8), Text( label, style: const TextStyle( color: Color(0xFF2563EB), fontSize: 13, fontWeight: FontWeight.w900, ), ), ], ) : const SizedBox.shrink(), ), ], ), ), ), ), ); } }