/// Renders the Top Bar widget for the FocusFlow Flutter UI. library; import 'package:flutter/material.dart'; import '../theme/focus_flow_tokens.dart'; /// Header bar for the compact Today view. class TopBar extends StatelessWidget { /// Creates a top bar with a display-ready [dateLabel]. const TopBar({required this.dateLabel, super.key}); /// Date label shown beside the date navigation controls. final String dateLabel; @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { final metrics = _TopBarMetrics.fromWidth(constraints.maxWidth); return SizedBox( height: _TopBarMetrics.referenceHeight, child: Row( children: [ SizedBox( width: metrics.titleWidth, height: _TopBarMetrics.referenceHeight, child: FittedBox( alignment: Alignment.centerLeft, fit: BoxFit.scaleDown, child: Text( 'Today', style: Theme.of(context).textTheme.headlineLarge?.copyWith( fontSize: metrics.titleSize, ), ), ), ), SizedBox(width: metrics.titleGap), _IconButton( icon: Icons.calendar_today, metrics: metrics, onPressed: () {}, ), _IconButton( icon: Icons.chevron_left, metrics: metrics, onPressed: () {}, ), SizedBox( width: metrics.dateWidth, height: metrics.controlHeight, child: Center( child: FittedBox( fit: BoxFit.scaleDown, child: Text( dateLabel, style: TextStyle( color: FocusFlowTokens.textPrimary, fontSize: metrics.dateSize, ), ), ), ), ), _IconButton( icon: Icons.chevron_right, metrics: metrics, onPressed: () {}, ), const Spacer(), _ModeToggle(metrics: metrics), SizedBox(width: metrics.settingsGap), _SettingsButton(metrics: metrics), ], ), ); }, ); } } class _TopBarMetrics { const _TopBarMetrics(this.scale); static const referenceHeight = 48.0; static const _referenceWidth = 900.0; static const _minimumScale = 0.44; factory _TopBarMetrics.fromWidth(double width) { final safeWidth = width.isFinite ? width : _referenceWidth; final scale = (safeWidth / _referenceWidth).clamp(_minimumScale, 1.0); return _TopBarMetrics(scale.toDouble()); } final double scale; double get titleWidth => 112 * scale; double get titleSize => FocusFlowTokens.pageTitleSize * scale; double get titleGap => 30 * scale; double get controlHeight => referenceHeight * scale; double get iconButtonSize => referenceHeight * scale; double get iconSize => 24 * scale; double get dateWidth => 144 * scale; double get dateSize => 17 * scale; double get modeWidth => 220 * scale; double get modeHeight => referenceHeight * scale; double get modeLabelSize => 17 * scale; double get settingsGap => 28 * scale; double get settingsWidth => 136 * scale; double get settingsHeight => referenceHeight * scale; double get settingsIconSize => 20 * scale; double get settingsTextSize => 15 * scale; double get settingsTextGap => 8 * scale; double get borderRadius => FocusFlowTokens.smallButtonRadius * scale; double get borderWidth => scale < 0.7 ? 0.8 : 1; EdgeInsets get buttonPadding => EdgeInsets.symmetric(horizontal: 12 * scale); } class _SettingsButton extends StatelessWidget { const _SettingsButton({required this.metrics}); final _TopBarMetrics metrics; @override Widget build(BuildContext context) { return OutlinedButton( onPressed: () {}, style: OutlinedButton.styleFrom( foregroundColor: FocusFlowTokens.textPrimary, side: BorderSide( color: FocusFlowTokens.subtleBorder, width: metrics.borderWidth, ), fixedSize: Size(metrics.settingsWidth, metrics.settingsHeight), minimumSize: Size.zero, padding: metrics.buttonPadding, tapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(metrics.borderRadius), ), ), child: FittedBox( fit: BoxFit.scaleDown, child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.wb_sunny_outlined, size: metrics.settingsIconSize), SizedBox(width: metrics.settingsTextGap), Text( 'Settings', style: TextStyle( fontSize: metrics.settingsTextSize, fontWeight: FontWeight.w600, ), ), ], ), ), ); } } class _IconButton extends StatelessWidget { const _IconButton({ required this.icon, required this.metrics, required this.onPressed, }); final IconData icon; final _TopBarMetrics metrics; final VoidCallback onPressed; @override Widget build(BuildContext context) { return IconButton( onPressed: onPressed, constraints: BoxConstraints.tightFor( width: metrics.iconButtonSize, height: metrics.iconButtonSize, ), color: FocusFlowTokens.textPrimary, iconSize: metrics.iconSize, padding: EdgeInsets.zero, icon: Icon(icon), visualDensity: VisualDensity.compact, ); } } class _ModeToggle extends StatelessWidget { const _ModeToggle({required this.metrics}); final _TopBarMetrics metrics; @override Widget build(BuildContext context) { return Container( height: metrics.modeHeight, width: metrics.modeWidth, decoration: BoxDecoration( borderRadius: BorderRadius.circular(metrics.borderRadius), border: Border.all( color: FocusFlowTokens.subtleBorder, width: metrics.borderWidth, ), ), child: Row( children: [ Expanded( child: Container( alignment: Alignment.center, decoration: BoxDecoration( color: FocusFlowTokens.glassPanelStrong, borderRadius: BorderRadius.circular(metrics.borderRadius), border: Border.all( color: FocusFlowTokens.navBorder, width: metrics.borderWidth, ), ), child: FittedBox( fit: BoxFit.scaleDown, child: Text( 'Compact', style: TextStyle(fontSize: metrics.modeLabelSize), ), ), ), ), Expanded( child: TextButton( onPressed: () {}, style: TextButton.styleFrom( minimumSize: Size.zero, padding: EdgeInsets.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), child: FittedBox( fit: BoxFit.scaleDown, child: Text( 'Normal', style: TextStyle( color: FocusFlowTokens.textPrimary, fontSize: metrics.modeLabelSize, ), ), ), ), ), ], ), ); } }