diff --git a/apps/design_system_gallery/lib/app/gallery_shell.dart b/apps/design_system_gallery/lib/app/gallery_shell.dart index d9a5079..9911658 100644 --- a/apps/design_system_gallery/lib/app/gallery_shell.dart +++ b/apps/design_system_gallery/lib/app/gallery_shell.dart @@ -8,12 +8,16 @@ import '../widgets/toolbar/toolbar.dart'; import 'gallery_app.directories.g.dart'; import 'home.dart'; +/// Width of the theme customization panel. +const kThemePanelWidth = 340.0; + +/// Widgetbook's breakpoint for desktop mode. +const kWidgetbookDesktopBreakpoint = 840.0; + +/// Animation duration for panel transitions. +const kPanelAnimationDuration = Duration(milliseconds: 250); + /// The main shell that wraps the widgetbook with custom Stream branding. -/// -/// This widget provides the overall layout including: -/// - Top toolbar with branding and controls -/// - Main widgetbook content area -/// - Optional theme customization panel class GalleryShell extends StatelessWidget { const GalleryShell({ super.key, @@ -28,6 +32,20 @@ class GalleryShell extends StatelessWidget { Widget build(BuildContext context) { final materialTheme = Theme.of(context); final isDark = materialTheme.brightness == .dark; + final screenWidth = MediaQuery.sizeOf(context).width; + + // Use overlay on small screens, side-by-side on large screens + final widgetbookWidth = showThemePanel ? screenWidth - kThemePanelWidth : screenWidth; + final useOverlay = widgetbookWidth < kWidgetbookDesktopBreakpoint; + + final widgetbook = Widgetbook.material( + lightTheme: materialTheme, + darkTheme: materialTheme, + themeMode: isDark ? .dark : .light, + directories: _collapseDirectories(directories), + home: const GalleryHomePage(), + appBuilder: (context, child) => PreviewWrapper(child: child), + ); return Scaffold( backgroundColor: context.streamColorScheme.backgroundApp, @@ -40,26 +58,25 @@ class GalleryShell extends StatelessWidget { ), // Content area below toolbar Expanded( - child: Row( + child: Stack( children: [ // Widgetbook area - Expanded( - child: Widgetbook.material( - lightTheme: materialTheme, - darkTheme: materialTheme, - themeMode: isDark ? .dark : .light, - directories: _collapseDirectories(directories), - home: const GalleryHomePage(), - appBuilder: (context, child) => PreviewWrapper(child: child), - ), + AnimatedPadding( + curve: Curves.easeInOut, + duration: kPanelAnimationDuration, + padding: .only(right: (!useOverlay && showThemePanel) ? kThemePanelWidth : 0), + child: widgetbook, ), // Theme customization panel - if (showThemePanel) ...[ - const SizedBox( - width: 340, - child: ThemeCustomizationPanel(), + Align( + alignment: .centerRight, + child: AnimatedSlide( + duration: kPanelAnimationDuration, + curve: Curves.easeInOut, + offset: showThemePanel ? Offset.zero : const Offset(1, 0), + child: const SizedBox(width: kThemePanelWidth, child: ThemeCustomizationPanel()), ), - ], + ), ], ), ), diff --git a/apps/design_system_gallery/lib/app/home.dart b/apps/design_system_gallery/lib/app/home.dart index 5ba65a5..25b759a 100644 --- a/apps/design_system_gallery/lib/app/home.dart +++ b/apps/design_system_gallery/lib/app/home.dart @@ -176,10 +176,12 @@ class _GettingStartedHint extends StatelessWidget { color: colorScheme.accentPrimary, ), SizedBox(width: spacing.sm), - Text( - 'Select a component from the sidebar to get started', - style: textTheme.captionDefault.copyWith( - color: colorScheme.accentPrimary, + Flexible( + child: Text( + 'Select a component from the sidebar to get started', + style: textTheme.captionDefault.copyWith( + color: colorScheme.accentPrimary, + ), ), ), ], diff --git a/apps/design_system_gallery/lib/main.dart b/apps/design_system_gallery/lib/main.dart index cc9edd8..72a4e89 100644 --- a/apps/design_system_gallery/lib/main.dart +++ b/apps/design_system_gallery/lib/main.dart @@ -1,7 +1,11 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:marionette_flutter/marionette_flutter.dart'; import 'app/gallery_app.dart'; void main() { + // Initialize Marionette only in debug mode + if (kDebugMode) MarionetteBinding.ensureInitialized(); runApp(const StreamDesignSystemGallery()); } diff --git a/apps/design_system_gallery/lib/primitives/colors.dart b/apps/design_system_gallery/lib/primitives/colors.dart index 1b1d34f..6eba653 100644 --- a/apps/design_system_gallery/lib/primitives/colors.dart +++ b/apps/design_system_gallery/lib/primitives/colors.dart @@ -146,10 +146,13 @@ class _FullWidthSwatchCard extends StatelessWidget { ), ), SizedBox(width: spacing.sm), - Text( - '— ${data.usage}', - style: textTheme.captionDefault.copyWith( - color: colorScheme.textTertiary, + Expanded( + child: Text( + '— ${data.usage}', + overflow: TextOverflow.ellipsis, + style: textTheme.captionDefault.copyWith( + color: colorScheme.textTertiary, + ), ), ), ], diff --git a/apps/design_system_gallery/macos/Runner/MainFlutterWindow.swift b/apps/design_system_gallery/macos/Runner/MainFlutterWindow.swift index 3cc05eb..9792888 100644 --- a/apps/design_system_gallery/macos/Runner/MainFlutterWindow.swift +++ b/apps/design_system_gallery/macos/Runner/MainFlutterWindow.swift @@ -8,6 +8,9 @@ class MainFlutterWindow: NSWindow { self.contentViewController = flutterViewController self.setFrame(windowFrame, display: true) + // Set minimum window size to prevent layout issues + self.minSize = NSSize(width: 400, height: 700) + RegisterGeneratedPlugins(registry: flutterViewController) super.awakeFromNib() diff --git a/apps/design_system_gallery/pubspec.yaml b/apps/design_system_gallery/pubspec.yaml index d584373..8f34e37 100644 --- a/apps/design_system_gallery/pubspec.yaml +++ b/apps/design_system_gallery/pubspec.yaml @@ -12,6 +12,7 @@ dependencies: flutter: sdk: flutter flutter_colorpicker: ^1.1.0 + marionette_flutter: ^0.3.0 provider: ^6.1.5+1 stream_core_flutter: path: ../../packages/stream_core_flutter @@ -23,6 +24,7 @@ dev_dependencies: build_runner: ^2.10.5 flutter_test: sdk: flutter + marionette_mcp: ^0.3.0 widgetbook_generator: ^3.20.1 flutter: