// SPDX-FileCopyrightText: 2026 FocusFlow contributors // SPDX-License-Identifier: AGPL-3.0-only /// Renders the Top Bar widget for the FocusFlow Flutter UI. library; import 'package:flutter/material.dart'; import '../theme/focus_flow_tokens.dart'; part 'top_bar/top_bar_icon_button.dart'; part 'top_bar/top_bar_metrics.dart'; part 'top_bar/top_bar_mode_toggle.dart'; part 'top_bar/top_bar_settings_button.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, this.onPreviousDate, this.onNextDate, this.onDatePressed, this.onDateLabelPressed, this.onOpenSettings, super.key, }); /// Date label shown beside the date navigation controls. final String dateLabel; /// Callback invoked when the previous-day control is activated. final VoidCallback? onPreviousDate; /// Callback invoked when the next-day control is activated. final VoidCallback? onNextDate; /// Callback invoked when the choose-date control is activated. final VoidCallback? onDatePressed; /// Callback invoked when the displayed date label is activated. final VoidCallback? onDateLabelPressed; /// Callback invoked when the Settings button is activated. final VoidCallback? onOpenSettings; /// Builds the widget subtree for this component. /// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data. @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, tooltip: 'Choose date', onPressed: onDatePressed, ), _IconButton( icon: Icons.chevron_left, metrics: metrics, tooltip: 'Previous day', onPressed: onPreviousDate, ), SizedBox( width: metrics.dateWidth, height: metrics.controlHeight, child: Tooltip( message: 'Scroll to current time', child: Semantics( button: true, label: 'Scroll to current time, $dateLabel', child: TextButton( key: const ValueKey('top-bar-date-button'), onPressed: onDateLabelPressed, style: TextButton.styleFrom( foregroundColor: FocusFlowTokens.textPrimary, padding: EdgeInsets.symmetric( horizontal: 6 * metrics.scale, ), minimumSize: Size( metrics.dateWidth, metrics.controlHeight, ), tapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( metrics.borderRadius, ), ), ), child: FittedBox( fit: BoxFit.scaleDown, child: Text( dateLabel, maxLines: 1, overflow: TextOverflow.visible, style: TextStyle( color: FocusFlowTokens.textPrimary, fontSize: metrics.dateSize, ), ), ), ), ), ), ), _IconButton( icon: Icons.chevron_right, metrics: metrics, tooltip: 'Next day', onPressed: onNextDate, ), const Spacer(), _ModeToggle(metrics: metrics), SizedBox(width: metrics.settingsGap), _SettingsButton(metrics: metrics, onPressed: onOpenSettings), ], ), ); }, ); } }