From 71eabc01a3d2c15646393db541a688662d57c908 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 00:59:48 +0000 Subject: [PATCH 1/4] Initial plan From 449b8c0532750a1291df27434ef901d37fa18af7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 01:32:04 +0000 Subject: [PATCH 2/4] fix: TitleBar height no longer shrinks when window is resized to smaller width (#1340) Co-authored-by: bdlukaa <45696119+bdlukaa@users.noreply.github.com> --- CHANGELOG.md | 1 + .../navigation/navigation_view/title_bar.dart | 5 +- test/navigation_view_test.dart | 186 ++++++++++++++++++ 3 files changed, 189 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39ce109aa..a63808c95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - **BREAKING** feat: `TreeViewItem.children` is now unmodifiable. Use `TreeViewController` methods (`addItem()`, `addItems()`, `removeItem()`, `moveItem()`) to modify tree structure. - feat: `TitleBar` now supports double-click callback to maximize or restore the window ([#1298](https://github.com/bdlukaa/fluent_ui/issues/1298)) - fix: Correctly apply `TitleBar`'s `isBackButtonEnabled` ([#1298](https://github.com/bdlukaa/fluent_ui/issues/1298)) +- fix: `TitleBar` height no longer shrinks when the window is resized to a smaller width ([#1340](https://github.com/bdlukaa/fluent_ui/issues/1340)) ## 4.14.0 diff --git a/lib/src/controls/navigation/navigation_view/title_bar.dart b/lib/src/controls/navigation/navigation_view/title_bar.dart index f02c66398..7d9fa9bcd 100644 --- a/lib/src/controls/navigation/navigation_view/title_bar.dart +++ b/lib/src/controls/navigation/navigation_view/title_bar.dart @@ -121,11 +121,10 @@ class TitleBar extends StatelessWidget { onPanUpdate: (_) => onDragUpdated?.call(), onDoubleTap: () => onDoubleTap?.call(), child: ConstrainedBox( - constraints: BoxConstraints( + constraints: BoxConstraints.tightFor( // according to documentation, increase the size of the title bar if // there is content - minHeight: content != null ? 48 : 32, - maxHeight: 48, + height: content != null ? 48 : 32, ), child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, diff --git a/test/navigation_view_test.dart b/test/navigation_view_test.dart index 2ae169273..22d524af2 100644 --- a/test/navigation_view_test.dart +++ b/test/navigation_view_test.dart @@ -969,4 +969,190 @@ void main() { }, ); }); + + // Regression test for https://github.com/bdlukaa/fluent_ui/issues/1340 + // TitleBar should not shrink in height when window is resized to smaller width + group('Issue #1340 - TitleBar height stability on window resize', () { + testWidgets( + 'TitleBar with content maintains 48px height at large window width', + (tester) async { + await tester.pumpWidget( + FluentApp( + home: SizedBox( + width: 1200, + height: 800, + child: NavigationView( + titleBar: const TitleBar( + title: Text('My App'), + content: SizedBox(width: 200, height: 32), + ), + pane: NavigationPane( + selected: 0, + displayMode: PaneDisplayMode.compact, + items: [ + PaneItem( + icon: const Icon(FluentIcons.home), + title: const Text('Home'), + body: const Center(child: Text('Home Page')), + ), + ], + ), + ), + ), + ), + ); + + await tester.pumpAndSettle(); + + final titleBar = find.byType(TitleBar); + expect(titleBar, findsOneWidget); + expect(tester.getSize(titleBar).height, 48.0); + }, + ); + + testWidgets( + 'TitleBar with content maintains 48px height at small window width', + (tester) async { + await tester.pumpWidget( + FluentApp( + home: SizedBox( + width: 300, + height: 800, + child: NavigationView( + titleBar: const TitleBar( + title: Text('My App'), + content: SizedBox(width: 200, height: 32), + ), + pane: NavigationPane( + selected: 0, + displayMode: PaneDisplayMode.compact, + items: [ + PaneItem( + icon: const Icon(FluentIcons.home), + title: const Text('Home'), + body: const Center(child: Text('Home Page')), + ), + ], + ), + ), + ), + ), + ); + + await tester.pumpAndSettle(); + + final titleBar = find.byType(TitleBar); + expect(titleBar, findsOneWidget); + expect(tester.getSize(titleBar).height, 48.0); + }, + ); + + testWidgets( + 'TitleBar height does not change when window width is reduced', + (tester) async { + Widget buildWithWidth(double width) { + return FluentApp( + home: SizedBox( + width: width, + height: 800, + child: NavigationView( + titleBar: const TitleBar( + title: Text('My App'), + content: SizedBox(width: 200, height: 32), + ), + pane: NavigationPane( + selected: 0, + displayMode: PaneDisplayMode.compact, + items: [ + PaneItem( + icon: const Icon(FluentIcons.home), + title: const Text('Home'), + body: const Center(child: Text('Home Page')), + ), + ], + ), + ), + ), + ); + } + + await tester.pumpWidget(buildWithWidth(1200)); + await tester.pumpAndSettle(); + + final titleBar = find.byType(TitleBar); + final heightAtLargeWidth = tester.getSize(titleBar).height; + expect(heightAtLargeWidth, 48.0); + + // Simulate window resize to smaller width + await tester.pumpWidget(buildWithWidth(300)); + await tester.pumpAndSettle(); + + final heightAtSmallWidth = tester.getSize(find.byType(TitleBar)).height; + expect(heightAtSmallWidth, 48.0); + expect(heightAtLargeWidth, equals(heightAtSmallWidth)); + }, + ); + + testWidgets( + 'TitleBar without content maintains 32px height regardless of window width', + (tester) async { + // At large window width + await tester.pumpWidget( + FluentApp( + home: SizedBox( + width: 1200, + height: 800, + child: NavigationView( + titleBar: const TitleBar(title: Text('My App')), + pane: NavigationPane( + selected: 0, + displayMode: PaneDisplayMode.expanded, + items: [ + PaneItem( + icon: const Icon(FluentIcons.home), + title: const Text('Home'), + body: const Center(child: Text('Home Page')), + ), + ], + ), + ), + ), + ), + ); + + await tester.pumpAndSettle(); + + final titleBar = find.byType(TitleBar); + expect(tester.getSize(titleBar).height, 32.0); + + // At small window width + await tester.pumpWidget( + FluentApp( + home: SizedBox( + width: 400, + height: 800, + child: NavigationView( + titleBar: const TitleBar(title: Text('My App')), + pane: NavigationPane( + selected: 0, + displayMode: PaneDisplayMode.expanded, + items: [ + PaneItem( + icon: const Icon(FluentIcons.home), + title: const Text('Home'), + body: const Center(child: Text('Home Page')), + ), + ], + ), + ), + ), + ), + ); + + await tester.pumpAndSettle(); + + expect(tester.getSize(find.byType(TitleBar)).height, 32.0); + }, + ); + }); } From 9363d4e1cc08928ce0a55f3a968dd8f571fd97d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 02:04:52 +0000 Subject: [PATCH 3/4] fix: _TitleSubtitleOverflow intrinsic height includes hidden children Co-authored-by: bdlukaa <45696119+bdlukaa@users.noreply.github.com> --- .../navigation/navigation_view/title_bar.dart | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/lib/src/controls/navigation/navigation_view/title_bar.dart b/lib/src/controls/navigation/navigation_view/title_bar.dart index 7d9fa9bcd..c9c6e5edf 100644 --- a/lib/src/controls/navigation/navigation_view/title_bar.dart +++ b/lib/src/controls/navigation/navigation_view/title_bar.dart @@ -330,13 +330,9 @@ class _RenderTitleSubtitleOverflow extends RenderBox var height = 0.0; var child = firstChild; while (child != null) { - final childParentData = - child.parentData! as _TitleSubtitleOverflowParentData; - if (!childParentData.isHidden) { - height = height > child.getMinIntrinsicHeight(width) - ? height - : child.getMinIntrinsicHeight(width); - } + height = height > child.getMinIntrinsicHeight(width) + ? height + : child.getMinIntrinsicHeight(width); child = childAfter(child); } return height; @@ -347,13 +343,9 @@ class _RenderTitleSubtitleOverflow extends RenderBox var height = 0.0; var child = firstChild; while (child != null) { - final childParentData = - child.parentData! as _TitleSubtitleOverflowParentData; - if (!childParentData.isHidden) { - height = height > child.getMaxIntrinsicHeight(width) - ? height - : child.getMaxIntrinsicHeight(width); - } + height = height > child.getMaxIntrinsicHeight(width) + ? height + : child.getMaxIntrinsicHeight(width); child = childAfter(child); } return height; From 36a1ed43f9a8412def3cc6fd63bc0d96d010006c Mon Sep 17 00:00:00 2001 From: Bruno D'Luka Date: Fri, 27 Mar 2026 19:47:17 -0300 Subject: [PATCH 4/4] fix: Correctly position titlebar in compact overlay mode --- example/lib/main.dart | 2 +- .../navigation/navigation_view/title_bar.dart | 24 ++++++++++++++++++- .../navigation/navigation_view/view.dart | 3 +-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index de8ec8089..ed5184b00 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -211,7 +211,7 @@ class _MyHomePageState extends State with WindowListener { appTheme.mode = ThemeMode.light; } }, - child: const Icon(WindowsIcons.lightbulb), + child: const Icon(WindowsIcons.lightbulb, size: 16), ), ), captionControls: const WindowButtons(), diff --git a/lib/src/controls/navigation/navigation_view/title_bar.dart b/lib/src/controls/navigation/navigation_view/title_bar.dart index 67ed9807c..6fc3e8261 100644 --- a/lib/src/controls/navigation/navigation_view/title_bar.dart +++ b/lib/src/controls/navigation/navigation_view/title_bar.dart @@ -31,6 +31,7 @@ class TitleBar extends StatelessWidget { this.subtitle, this.content, this.endHeader, + this.height, this.captionControls, this.onDragStarted, this.onDragEnded, @@ -84,8 +85,20 @@ class TitleBar extends StatelessWidget { /// Usually an [AutoSuggestBox] widget. final Widget? content; + /// The right header widget. + /// + /// Usually an [Icon] widget. final Widget? endHeader; + /// The height of the title bar. + /// + /// If not provided, the height is calculated based on the [content]. + /// + /// See also: + /// + /// * [calculateHeight], which calculates the height based on the content. + final double? height; + /// The controls of the window, if any. final Widget? captionControls; @@ -104,6 +117,15 @@ class TitleBar extends StatelessWidget { /// The callback that is called when the title bar is double-tapped. final VoidCallback? onDoubleTap; + static double calculateHeight(Widget? titleBar) { + if (titleBar == null) return 0; + if (titleBar is TitleBar) { + if (titleBar.height != null) return titleBar.height!; + if (titleBar.content != null) return 48; + } + return 32; + } + @override Widget build(BuildContext context) { assert(debugCheckHasFluentTheme(context)); @@ -124,7 +146,7 @@ class TitleBar extends StatelessWidget { constraints: BoxConstraints.tightFor( // according to documentation, increase the size of the title bar if // there is content - height: content != null ? 48 : 32, + height: TitleBar.calculateHeight(this), ), child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, diff --git a/lib/src/controls/navigation/navigation_view/view.dart b/lib/src/controls/navigation/navigation_view/view.dart index 79364eb64..48870d1de 100644 --- a/lib/src/controls/navigation/navigation_view/view.dart +++ b/lib/src/controls/navigation/navigation_view/view.dart @@ -230,7 +230,6 @@ class NavigationView extends StatefulWidget { void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add(DiagnosticsProperty('titleBar', titleBar)) ..add(DiagnosticsProperty('pane', pane)) ..add( DiagnosticsProperty( @@ -825,7 +824,7 @@ class NavigationViewState extends State { children: [ Padding( padding: EdgeInsetsDirectional.only( - top: 38, + top: TitleBar.calculateHeight(widget.titleBar), start: pane.size?.compactWidth ?? kCompactNavigationPaneWidth, ), child: content,