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..30a84026 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); @@ -264,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!, @@ -273,7 +274,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 +327,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" 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);