From eebc642138c5524c9297ff7fddab8d7a17ef0f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20R=C3=B6hner?= Date: Thu, 20 Nov 2025 11:19:10 +0100 Subject: [PATCH 1/3] fix: respect sidebar decoration color in macos window (#587) --- CHANGELOG.md | 4 ++++ lib/src/layout/window.dart | 21 ++++++++++----------- pubspec.yaml | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10816f76..bacfa4a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [2.2.3] +### 🛠 Fixed 🛠 +- Fixed sidebar background painting when wallpaper tinting is disabled: the macOS sidebar now stays transparent unless a decoration color is provided (previously showed a black strip). Addresses #587. + ## [2.2.2] ### 🛠 Fixed 🛠 - Fixed setState called after dispose issue in MacosPulldownButton. diff --git a/lib/src/layout/window.dart b/lib/src/layout/window.dart index 5e0f447c..d9dc330e 100644 --- a/lib/src/layout/window.dart +++ b/lib/src/layout/window.dart @@ -195,18 +195,15 @@ class _MacosWindowState extends State { } final MacosThemeData theme = MacosTheme.of(context); late Color backgroundColor = widget.backgroundColor ?? theme.canvasColor; - late Color sidebarBackgroundColor; + late Color? sidebarBackgroundColor; late Color endSidebarBackgroundColor; Color dividerColor = theme.dividerColor; final isMac = !kIsWeb && defaultTargetPlatform == TargetPlatform.macOS; // Respect the sidebar color override from parent if one is given - if (sidebar?.decoration?.color != null) { - sidebarBackgroundColor = sidebar!.decoration!.color!; - } else { - sidebarBackgroundColor = MacosColors.transparent; - } + sidebarBackgroundColor = + sidebar?.decoration?.color ?? (kIsWeb ? theme.canvasColor : null); // Set the application window's brightness on macOS MacOSBrightnessOverrideHandler.ensureMatchingBrightness(theme.brightness); @@ -273,7 +270,7 @@ class _MacosWindowState extends State { ).normalize(), child: kIsWeb ? ColoredBox( - color: theme.canvasColor, + color: sidebarBackgroundColor ?? theme.canvasColor, child: Column( children: [ // If an app is running on macOS, apply @@ -326,10 +323,12 @@ class _MacosWindowState extends State { : TransparentMacOSSidebar( state: sidebarState, child: DecoratedBox( - decoration: const BoxDecoration( - color: Color.fromRGBO(0, 0, 0, 1.0), - backgroundBlendMode: BlendMode.clear, - ), + decoration: + (sidebar.decoration ?? const BoxDecoration()) + .copyWith( + // Only paint if the caller set a color; null preserves native transparency. + color: sidebarBackgroundColor, + ), child: Column( children: [ // If an app is running on macOS, apply diff --git a/pubspec.yaml b/pubspec.yaml index 886bb6b4..c6355f3f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: macos_ui description: Flutter widgets and themes implementing the current macOS design language. -version: 2.2.2 +version: 2.2.3 homepage: "https://macosui.dev" repository: "https://github.com/GroovinChip/macos_ui" From dfae50f0c622254d8c9e03f3831d3fa61b16b34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20R=C3=B6hner?= Date: Thu, 9 Jul 2026 15:14:02 +0200 Subject: [PATCH 2/3] fix: paint sidebar background color exactly once The sidebar background was painted by both the wrapping AnimatedContainer and the inner ColoredBox/DecoratedBox, so a semi-transparent Sidebar.decoration.color was blended twice and rendered darker than requested. Drop the redundant color from the AnimatedContainer so it is painted a single time. --- lib/src/layout/window.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/layout/window.dart b/lib/src/layout/window.dart index d9dc330e..30a84026 100644 --- a/lib/src/layout/window.dart +++ b/lib/src/layout/window.dart @@ -261,7 +261,11 @@ class _MacosWindowState extends State { child: AnimatedContainer( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, - color: sidebarBackgroundColor, + // The sidebar background is painted exactly once by the inner + // ColoredBox (web) / DecoratedBox (macOS) below. Painting it + // here too would blend a semi-transparent + // Sidebar.decoration.color twice, making it darker than + // requested. constraints: BoxConstraints( minWidth: sidebar.minWidth, maxWidth: sidebar.maxWidth!, From de44e732d0aba7d15894238d9c290eab8e2a3077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20R=C3=B6hner?= Date: Thu, 9 Jul 2026 15:14:16 +0200 Subject: [PATCH 3/3] test: cover sidebar background painting Assert the sidebar stays transparent when no Sidebar.decoration.color is provided and uses the provided color otherwise, guarding the transparent-by-default behavior from #587. --- test/layout/window_test.dart | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/test/layout/window_test.dart b/test/layout/window_test.dart index 1d9bb9ec..eb9fc42c 100644 --- a/test/layout/window_test.dart +++ b/test/layout/window_test.dart @@ -1,6 +1,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:macos_ui/macos_ui.dart'; +import 'package:macos_window_utils/widgets/transparent_macos_sidebar.dart'; void main() { group('MacosWindow', () { @@ -15,6 +16,7 @@ void main() { bool dragClosed = true, double? dragClosedBuffer, double? snapToStartBuffer, + BoxDecoration? decoration, }) { return Sidebar( builder: (context, scrollController) => const Text('Hello there'), @@ -24,6 +26,7 @@ void main() { dragClosed: dragClosed, dragClosedBuffer: dragClosedBuffer, snapToStartBuffer: snapToStartBuffer, + decoration: decoration, ); } @@ -54,6 +57,50 @@ void main() { expect(tester.widget(backgroundFinder).left, 0); } + // The sidebar background is painted by the DecoratedBox inside the + // TransparentMacOSSidebar. Grabbing its decoration lets us assert what + // color (if any) is painted for the sidebar. + BoxDecoration sidebarDecoration(WidgetTester tester) { + final decoratedBox = tester.widget( + find + .descendant( + of: find.byType(TransparentMacOSSidebar), + matching: find.byType(DecoratedBox), + ) + .first, + ); + return decoratedBox.decoration as BoxDecoration; + } + + group('background', () { + testWidgets( + 'stays transparent when no decoration color is provided, so the ' + 'native sidebar material shows through', + (tester) async { + await tester.pumpWidget(viewBuilder(sidebarBuilder())); + + expect(sidebarDecoration(tester).color, isNull); + + await tester.pump(Duration.zero); + }, + ); + + testWidgets('is painted with the provided Sidebar.decoration color', ( + tester, + ) async { + const color = MacosColors.systemBlueColor; + await tester.pumpWidget( + viewBuilder( + sidebarBuilder(decoration: const BoxDecoration(color: color)), + ), + ); + + expect(sidebarDecoration(tester).color, color); + + await tester.pump(Duration.zero); + }); + }); + testWidgets('initial width equals startWidth', (tester) async { final sidebar = sidebarBuilder(); final view = viewBuilder(sidebar);