import 'package:jaspr/jaspr.dart'; import 'package:jaspr_router/jaspr_router.dart'; import '../state/theme_state.dart'; import '../config/app_config.dart'; class Header extends StatefulComponent { const Header({super.key}); @override State
createState() => _HeaderState(); } class _HeaderState extends State
{ bool _isMenuOpen = false; void _toggleMenu() { setState(() { _isMenuOpen = !_isMenuOpen; }); } @override Iterable build(BuildContext context) sync* { var activePath = RouteState.of(context).location; var themeState = ThemeState.of(context); yield header( classes: themeState.isDarkMode ? 'bg-gray-800 shadow-md' : 'bg-white shadow-md', [ div( classes: 'max-w-7xl mx-auto px-4 sm:px-6 lg:px-8', [ div( classes: 'flex justify-between items-center h-16', [ // Logo Link( to: '/', child: div( classes: 'flex items-center', [ img( src: AppConfig.appLogo, alt: 'Logo', classes: 'h-8 w-8 mr-2', ), span( classes: 'font-bold text-xl ${themeState.isDarkMode ? 'text-white' : 'text-gray-900'}', [text(AppConfig.appName)], ), ], ), ), // Mobile menu button div( classes: 'md:hidden', [ button( classes: '${themeState.isDarkMode ? 'text-gray-300 hover:text-white' : 'text-gray-600 hover:text-gray-900'} focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500', events: {'click': (e) => _toggleMenu()}, [ span(classes: 'sr-only', [text('Open main menu')]), // Hamburger icon // svg( // classes: 'h-6 w-6', // attributes: { // 'fill': 'none', // 'viewBox': '0 0 24 24', // 'stroke': 'currentColor', // 'aria-hidden': 'true', // }, // [ // path( // attributes: { // 'stroke-linecap': 'round', // 'stroke-linejoin': 'round', // 'stroke-width': '2', // 'd': 'M4 6h16M4 12h16M4 18h16', // }, // [], // ), // ], // ), ], ), ], ), // Desktop navigation nav( classes: 'hidden md:flex space-x-4', [ for (var entry in AppConfig.navLinks.entries) Link( to: entry.value, child: div( classes: 'px-3 py-2 rounded-md text-sm font-medium ${activePath == entry.value ? (themeState.isDarkMode ? 'bg-gray-900 text-white' : 'bg-gray-200 text-gray-900') : (themeState.isDarkMode ? 'text-gray-300 hover:bg-gray-700 hover:text-white' : 'text-gray-700 hover:bg-gray-200 hover:text-gray-900')}', [text(entry.key)], ), ), ], ), // Button( // label: 'Button 1', // onPressed: () { // print("Button 1 pressed"); // }, // ), // Theme toggle button button( // classes: // 'ml-4 p-2 rounded-md ${themeState.isDarkMode ? 'bg-gray-700 text-yellow-400' : 'bg-gray-200 text-gray-800'}', events: events(onClick: () { print('Clicked!'); // themeState.toggleTheme(!themeState.isDarkMode); }), [ // text(themeState.isDarkMode ? '☀️' : '🌙'), // text(themeState.isDarkMode ? '☀️' : '🌙'), ], ), ], ), ], ), // Mobile navigation div( classes: 'md:hidden ${_isMenuOpen ? '' : 'hidden'}', [ div( classes: 'px-2 pt-2 pb-3 space-y-1 sm:px-3', [ for (var entry in AppConfig.navLinks.entries) Link( to: entry.value, child: div( classes: 'block px-3 py-2 rounded-md text-base font-medium ${activePath == entry.value ? (themeState.isDarkMode ? 'bg-gray-900 text-white' : 'bg-gray-200 text-gray-900') : (themeState.isDarkMode ? 'text-gray-300 hover:bg-gray-700 hover:text-white' : 'text-gray-700 hover:bg-gray-200 hover:text-gray-900')}', [text(entry.key)], ), ), ], ), ], ), ], ); } } class Button extends StatelessComponent { const Button({required this.label, required this.onPressed, super.key}); final String label; final VoidCallback onPressed; @override Iterable build(BuildContext context) sync* { yield button( onClick: onPressed, [text(label)], ); } }