import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import '../../models/nav_item.dart'; class NavItemTile extends StatelessWidget { final NavItem item; final String currentRoute; const NavItemTile({ super.key, required this.item, required this.currentRoute, }); @override Widget build(BuildContext context) { if (item.hasChildren) { return _GroupTile(item: item, currentRoute: currentRoute); } return _LeafTile(item: item, currentRoute: currentRoute); } } // ── Leaf (item sin hijos) ────────────────────────────────────────────────── class _LeafTile extends StatelessWidget { final NavItem item; final String currentRoute; const _LeafTile({required this.item, required this.currentRoute}); bool get _isActive => item.route != null && currentRoute == item.route; @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; final tt = Theme.of(context).textTheme; return Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 1), child: Material( color: _isActive ? cs.secondaryContainer : Colors.transparent, borderRadius: BorderRadius.circular(12), child: InkWell( borderRadius: BorderRadius.circular(12), onTap: () => context.go(item.route!), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), child: Row( children: [ Icon( item.icon, size: 20, color: _isActive ? cs.onSecondaryContainer : cs.onSurfaceVariant, ), const SizedBox(width: 12), Expanded( child: Text( item.label, style: tt.bodyMedium?.copyWith( color: _isActive ? cs.onSecondaryContainer : cs.onSurface, fontWeight: _isActive ? FontWeight.w600 : FontWeight.normal, ), ), ), ], ), ), ), ), ); } } // ── Group (item con hijos, expansible) ──────────────────────────────────── class _GroupTile extends StatefulWidget { final NavItem item; final String currentRoute; const _GroupTile({required this.item, required this.currentRoute}); @override State<_GroupTile> createState() => _GroupTileState(); } class _GroupTileState extends State<_GroupTile> { late bool _expanded; @override void initState() { super.initState(); _expanded = widget.item.isActiveOrAncestor(widget.currentRoute); } @override void didUpdateWidget(_GroupTile old) { super.didUpdateWidget(old); if (old.currentRoute != widget.currentRoute) { if (widget.item.isActiveOrAncestor(widget.currentRoute)) { _expanded = true; } } } @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; final tt = Theme.of(context).textTheme; final isAncestor = widget.item.isActiveOrAncestor(widget.currentRoute); return Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 1), child: Theme( // Quita el separador por defecto del ExpansionTile data: Theme.of(context).copyWith(dividerColor: Colors.transparent), child: ExpansionTile( initiallyExpanded: _expanded, onExpansionChanged: (v) => setState(() => _expanded = v), tilePadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 0), childrenPadding: const EdgeInsets.only(left: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), collapsedShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), backgroundColor: isAncestor ? cs.surfaceContainerHigh : Colors.transparent, collapsedBackgroundColor: Colors.transparent, leading: Icon( widget.item.icon, size: 20, color: isAncestor ? cs.primary : cs.onSurfaceVariant, ), title: Text( widget.item.label, style: tt.bodyMedium?.copyWith( color: isAncestor ? cs.primary : cs.onSurface, fontWeight: isAncestor ? FontWeight.w600 : FontWeight.normal, ), ), children: widget.item.children .map((child) => NavItemTile( item: child, currentRoute: widget.currentRoute, )) .toList(), ), ), ); } }