diff --git a/.github/workflows/smoke-stacks.yml b/.github/workflows/smoke-stacks.yml new file mode 100644 index 0000000..0ac7c0f --- /dev/null +++ b/.github/workflows/smoke-stacks.yml @@ -0,0 +1,28 @@ +name: Smoke test stacks + +on: + pull_request: + paths: + - 'src/ui-ux-pro-max/data/stacks/**' + - 'src/ui-ux-pro-max/scripts/**' + - 'cli/assets/data/stacks/**' + - 'cli/assets/scripts/**' + - 'scripts/smoke-stacks.sh' + - '.github/workflows/smoke-stacks.yml' + push: + branches: [main] + workflow_dispatch: + +jobs: + smoke: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.x' + + - name: Run stack smoke test + run: bash scripts/smoke-stacks.sh diff --git a/README.md b/README.md index 635e9ce..578b95d 100755 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ Each rule includes: - **161 Color Palettes** - Industry-specific palettes aligned 1:1 with the 161 product types - **57 Font Pairings** - Curated typography combinations with Google Fonts imports - **25 Chart Types** - Recommendations for dashboards and analytics -- **17 Tech Stacks** - React, Next.js, Astro, Vue, Nuxt.js, Nuxt UI, Svelte, SwiftUI, React Native, Flutter, HTML+Tailwind, shadcn/ui, Jetpack Compose, Angular, Laravel, Three.js, JavaFX +- **22 Tech Stacks** - React, Next.js, Astro, Vue, Nuxt.js, Nuxt UI, Svelte, SwiftUI, React Native, Flutter, HTML+Tailwind, shadcn/ui, Jetpack Compose, Angular, Laravel, Three.js, JavaFX, WPF, WinUI 3, UWP, Avalonia, Uno Platform - **99 UX Guidelines** - Best practices, anti-patterns, and accessibility rules - **161 Reasoning Rules** - Industry-specific design system generation (NEW in v2.0) diff --git a/cli/assets/data/stacks/avalonia.csv b/cli/assets/data/stacks/avalonia.csv new file mode 100644 index 0000000..52dbae2 --- /dev/null +++ b/cli/assets/data/stacks/avalonia.csv @@ -0,0 +1,57 @@ +No,Category,Guideline,Description,Do,Don't,Code Good,Code Bad,Severity,Docs URL +1,XAML,Use Avalonia XAML namespace,Avalonia has its own XAML namespace not WPF,xmlns= for Avalonia-specific namespace,WPF xmlns or UWP xmlns,"","",High,https://docs.avaloniaui.net/docs/fundamentals/avalonia-xaml +2,XAML,Use compiled bindings with x:DataType,Enable compile-time binding validation,x:DataType on root or DataTemplate for compiled bindings,Reflection-based bindings in production,""," without x:DataType",High,https://docs.avaloniaui.net/docs/data-binding/compiled-bindings +3,XAML,Enable compiled bindings globally,AvaloniaUseCompiledBindingsByDefault in csproj makes every binding require x:DataType and is required for trim-safe Native AOT,AvaloniaUseCompiledBindingsByDefault MSBuild property in csproj,Relying on runtime binding resolution,"true","No compiled binding enforcement",High,https://docs.avaloniaui.net/docs/data-binding/compiled-bindings +4,XAML,Use #name shorthand for element-to-element bindings,Compiled bindings cannot resolve {Binding ElementName=...} - use the #name shorthand which relies on NameScope lookup,#name shorthand referencing x:Name controls in the same NameScope,ElementName binding inside a compiled-binding scope,""," under compiled bindings",Medium,https://docs.avaloniaui.net/docs/data-binding/compiled-bindings +5,Styling,Use CSS-like selectors,Avalonia uses selectors not implicit styles,Selectors targeting control types classes and pseudoclasses,WPF-style implicit Style with TargetType,"",""," for hover effects",Medium,https://docs.avaloniaui.net/docs/styling/pseudoclasses +7,Styling,Use nesting selectors,Child and descendant combinators for scoped styles,> for direct child and space for descendant,Flat selectors that match too broadly,"","","CornerRadius=""4"" on every Button in the page",Medium,https://learn.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/xaml-styles +16,Styling,Use VisualStateManager for visual states,Define visual states with Setters that change properties when triggered,VisualStateGroup containing VisualStates with Setter targets,Toggling Visibility from code-behind on SizeChanged,"","SizeChanged handler that flips Orientation in code-behind",High,https://learn.microsoft.com/en-us/windows/uwp/design/layout/layouts-with-xaml +17,Navigation,Use Frame for page navigation,Windows.UI.Xaml.Controls.Frame for UWP page navigation,Frame.Navigate with typed parameters,Swapping UserControls manually,"rootFrame.Navigate(typeof(DetailPage), itemId);","contentArea.Content = new DetailPage();",Medium,https://learn.microsoft.com/en-us/windows/uwp/design/basics/navigate-between-two-pages +18,Navigation,Handle back button correctly,Provide an in-app Back button styled with NavigationBackButtonNormalStyle and handle SystemNavigationManager.BackRequested for hardware back gamepad B and Tablet-Mode back; also handle CoreDispatcher.AcceleratorKeyActivated for Alt+Left,In-app NavigationBackButtonNormalStyle button plus SystemNavigationManager.BackRequested handler,Relying on the deprecated title-bar back button (AppViewBackButtonVisibility) or ignoring system back signals,"SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;","No back button support on phone or tablet",High,https://learn.microsoft.com/en-us/windows/uwp/ui-input/back-navigation +19,Navigation,Support deep linking with protocol activation,Respond to URI activation and toast taps,OnActivated handler with proper page routing,Ignoring activation arguments,"protected override void OnActivated(IActivatedEventArgs args) { if (args.Kind == ActivationKind.Protocol) { ... } }","Empty OnActivated ignoring URI parameters",Medium,https://learn.microsoft.com/en-us/windows/uwp/launch-resume/handle-uri-activation +20,Navigation,Use ConnectedAnimations for continuity,Smooth transitions between pages,ConnectedAnimationService for shared element transitions,Abrupt page transitions with no visual continuity,"ConnectedAnimationService.GetForCurrentView().PrepareToAnimate(""image"", sourceImage);","No transition animation between list and detail",Low,https://learn.microsoft.com/en-us/windows/uwp/design/motion/connected-animation +21,Data Binding,Implement INotifyPropertyChanged,Enable UI updates on property changes,INotifyPropertyChanged on all ViewModels,Auto-properties without notification,"public string Title { get => _title; set { _title = value; OnPropertyChanged(); } }","public string Title { get; set; } expecting UI updates",High,https://learn.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth +22,Data Binding,Use ObservableCollection for lists,Collection change notifications for ItemsSources,ObservableCollection for bound lists,List for data-bound collections,"ObservableCollection Items { get; } = new();","List Items { get; set; } = new();",High,https://learn.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth +23,Data Binding,Use function bindings with x:Bind,Call static methods directly in markup,x:Bind to static converter methods,IValueConverter for trivial transforms,"","Full IValueConverter class for bool to Visibility",Medium,https://learn.microsoft.com/en-us/windows/uwp/data-binding/function-bindings +24,Data Binding,Specify Mode on x:Bind,x:Bind defaults to OneTime not OneWay,Mode=OneWay or TwoWay when live updates needed,Omitting Mode and getting stale UI,"Text=""{x:Bind Title, Mode=OneWay}""","Text=""{x:Bind Title}"" expecting live updates",High,https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/x-bind-markup-extension +25,Data Binding,Use CollectionViewSource for grouping,Group and sort collections declaratively,CollectionViewSource for grouped ListView and GridView,Manual grouping logic in code-behind,"","Manual loop building grouped StackPanels",Medium,https://learn.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth +26,Performance,Use ListView and GridView virtualization,Only creates containers for visible items,Default virtualization in ListView and GridView,Setting ItemsPanel to non-virtualizing panel," (virtualizes by default)","",High,https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/optimize-gridview-and-listview +27,Performance,Use ISupportIncrementalLoading,Load data on demand as user scrolls,ISupportIncrementalLoading for large datasets,Loading entire collection upfront,"class IncrementalSource : ObservableCollection, ISupportIncrementalLoading","await LoadAll() loading 50K items at startup",Medium,https://learn.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth +28,Performance,Reduce XAML visual tree depth,Simpler trees layout and render faster,Flat templates with minimal nesting,Deeply nested panels in DataTemplates," in item template","... 8 levels in item template",Medium,https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/optimize-xaml-loading +29,Performance,Use compiled bindings in DataTemplates,x:Bind in templates requires x:DataType,x:DataType on DataTemplate for compiled bindings,{Binding} in item templates for large lists,"","",High,https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/x-bind-markup-extension +30,Performance,Profile with Visual Studio diagnostics,Measure before optimizing,Application Timeline and Memory Usage tools,Guessing at performance problems,"VS Diagnostic Tools > Application Timeline","Optimizing without profiling data",Medium,https://learn.microsoft.com/en-us/visualstudio/profiling/application-timeline +31,Threading,Use async/await for all IO,Keep UI thread responsive,async/await for file network and database operations,Synchronous IO blocking the UI thread,"var file = await StorageFile.GetFileFromPathAsync(path);","StorageFile.GetFileFromPathAsync(path).AsTask().Result;",High,https://learn.microsoft.com/en-us/windows/uwp/threading-async/asynchronous-programming-universal-windows-platform-apps +32,Threading,Use CoreDispatcher for UI thread access,Post work back to the UI thread from background,Dispatcher.RunAsync from background threads,Touching UI elements from background threads,"await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Status = ""Done"");","textBlock.Text = ""Done"" from Task.Run",High,https://learn.microsoft.com/en-us/uwp/api/windows.ui.core.coredispatcher +33,Threading,Offload CPU work with Task.Run,Keep compute-heavy work off UI thread,Task.Run for CPU-bound operations,Heavy computation blocking UI,"var result = await Task.Run(() => ProcessData(items));","var result = ProcessData(items); freezing UI",High,https://learn.microsoft.com/en-us/windows/uwp/threading-async/asynchronous-programming-universal-windows-platform-apps +34,Threading,Use IProgress for status updates,Report progress from background operations,IProgress for progress reporting to UI,Polling shared variables for progress,"var progress = new Progress(p => ProgressBar.Value = p); await Task.Run(() => Process(progress));","while (!done) { await Task.Delay(100); check shared field; }",Medium,https://learn.microsoft.com/en-us/dotnet/api/system.progress-1 +35,Adaptive,Use AdaptiveTrigger for responsive layouts,MinWindowWidth and MinWindowHeight triggers fire at standard breakpoints (640 small / 1008 medium),AdaptiveTrigger inside VisualState.StateTriggers with the 640 and 1008 breakpoints,Fixed layouts for a single screen size,"","Single-column layout at all widths",High,https://learn.microsoft.com/en-us/windows/uwp/design/layout/layouts-with-xaml +36,Adaptive,Design for multiple device families,Phone tablet desktop Xbox and HoloLens,DeviceFamily-specific views and resources,Desktop-only design ignoring other form factors,"DeviceFamily-Mobile/MainPage.xaml for phone-specific layout","Fixed 1920x1080 layout",Medium,https://learn.microsoft.com/en-us/windows/uwp/design/layout/screen-sizes-and-breakpoints-for-responsive-design +37,Adaptive,Use RelativePanel for adaptive positioning,Controls position relative to each other,RelativePanel for layouts that reflow at breakpoints,Absolute positioning or fixed margins,"","Full ControlTemplate copy to change background color",High,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/xaml-styles#lightweight-styling +11,Styling,Use WinUI theme resources,Consistent Fluent Design colors and brushes,WinUI theme resource keys for colors,Hardcoded hex color values,"Background=""{ThemeResource CardBackgroundFillColorDefaultBrush}""","Background=""#FF2D2D30""",High,https://learn.microsoft.com/en-us/windows/apps/design/signature-experiences/color +12,Styling,Support light and dark themes,Respect user and system theme preference,ThemeResource for theme-adaptive values,Hardcoded colors that break in dark mode,"Foreground=""{ThemeResource TextFillColorPrimaryBrush}""","Foreground=""Black""",High,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/xaml-theme-resources +13,Styling,Use Fluent Design system,Acrylic Mica Reveal and rounded corners,Built-in Fluent materials and effects,Custom blur and shadow implementations,"","Custom CompositionBrush recreating acrylic",Medium,https://learn.microsoft.com/en-us/windows/apps/design/signature-experiences/materials +14,Navigation,Use Frame for page navigation,Microsoft.UI.Xaml.Controls.Frame for WinUI 3 page navigation,Frame.Navigate with page types and parameters,Swapping UserControls in a ContentControl,"rootFrame.Navigate(typeof(SettingsPage), parameter);","contentArea.Content = new SettingsControl();",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/ui/navigation/navigate-between-two-pages +15,Navigation,Pass typed navigation parameters,Type-safe data passing between pages,Typed parameter in OnNavigatedTo,Dictionary or string parsing for parameters,"protected override void OnNavigatedTo(NavigationEventArgs e) { var item = (Item)e.Parameter; }","var id = int.Parse(e.Parameter.ToString());",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/ui/navigation/navigate-between-two-pages +16,Navigation,Handle back navigation,WinUI 3 uses NavigationView.BackRequested instead of UWP SystemNavigationManager,Register NavigationView.BackRequested handler and manage back stack,"Ignoring back navigation","navigationView.BackRequested += OnBackRequested;","No back button support",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/ui/navigation/navigation-history-and-backwards-navigation +17,Navigation,Use deep linking,Handle protocol activation so URIs route to the right page,Register protocol then check ExtendedActivationKind.Protocol on activation,Single entry point ignoring activation context,"AppInstance.GetCurrent().GetActivatedEventArgs() with ExtendedActivationKind.Protocol","Ignoring activation arguments",Medium,https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/applifecycle/applifecycle-rich-activation +18,Data Binding,Use ObservableCollection for lists,Notifies UI of collection changes,ObservableCollection for bound ItemsSources,List for bound collections,"ObservableCollection Items { get; } = new();","List Items { get; set; } = new();",High,https://learn.microsoft.com/en-us/windows/apps/develop/data-binding/data-binding-in-depth +19,Data Binding,Use INotifyPropertyChanged,Enable property change notification for UI updates,INotifyPropertyChanged on ViewModels,Properties without notification,"public string Name { get => _name; set => SetProperty(ref _name, value); }","public string Name { get; set; } without notification",High,https://learn.microsoft.com/en-us/windows/apps/develop/data-binding/data-binding-in-depth +20,Data Binding,Use function binding with x:Bind,Call methods directly in bindings,x:Bind with method references for transforms,IValueConverter for simple logic,"","IValueConverter class for bool to visibility",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/data-binding/function-bindings +21,Data Binding,Specify Mode explicitly on x:Bind,x:Bind defaults to OneTime not OneWay,Mode=OneWay or Mode=TwoWay when updates needed,Forgetting Mode and getting stale UI,"Text=""{x:Bind Title, Mode=OneWay}""","Text=""{x:Bind Title}"" expecting live updates",High,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/x-bind-markup-extension +22,Performance,Use ItemsRepeater for custom lists,Virtualizing layout with full control,ItemsRepeater for custom list layouts,ListView for highly customized item layouts,"","ListView with heavily modified template and removed chrome",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/ui/controls/items-repeater +23,Performance,Use incremental loading,Load data on demand as user scrolls,ISupportIncrementalLoading for large data sets,Loading entire dataset upfront,"class IncrementalItemSource : ObservableCollection, ISupportIncrementalLoading","await LoadAllItems() on page load for 10K items",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/data-binding/data-binding-in-depth +24,Performance,Reduce visual tree complexity,Simpler trees render faster,Minimal nesting in DataTemplates,Deeply nested panels in item templates,"","... 8 levels deep",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/performance/optimize-xaml-loading +25,Performance,Use compiled bindings over reflection,x:Bind generates code at compile time,x:Bind for hot paths and list items,{Binding} in DataTemplates and frequently updated UI,"","",High,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/x-bind-markup-extension +26,Threading,Use DispatcherQueue not Dispatcher,WinUI 3 uses Microsoft.UI.Dispatching.DispatcherQueue instead of UWP CoreDispatcher,DispatcherQueue.TryEnqueue for UI thread access,Dispatcher.RunAsync (UWP pattern),"_dispatcherQueue.TryEnqueue(() => Status = ""Done"");","Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => ...);",High,https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.dispatching.dispatcherqueue +27,Threading,Use async/await for IO operations,Keep UI responsive during file and network access,async/await for IO so the UI thread keeps rendering,Synchronous IO on UI thread,"var data = await httpClient.GetStringAsync(url);","var data = httpClient.GetStringAsync(url).Result;",High,https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/ +28,Threading,Use Task.Run for CPU-bound work,Offload compute to thread pool,Task.Run for heavy computation,Long-running CPU work on UI thread,"var result = await Task.Run(() => ProcessLargeDataSet());","var result = ProcessLargeDataSet(); blocking UI",High,https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-based-asynchronous-programming +29,Packaging,Use WinAppSDK correctly,Windows App SDK provides the runtime,WinAppSDK NuGet package and WindowsAppSDK bootstrapper,Mixing UWP and WinUI 3 APIs,"","Using Windows.UI.Xaml instead of Microsoft.UI.Xaml",High,https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/ +30,Packaging,Use unpackaged or packaged appropriately,Choose deployment model for your scenario,Packaged (MSIX) for Store distribution,Unpackaged without considering API limitations,"None for unpackaged","Assuming all APIs work in unpackaged mode",Medium,https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/deploy-packaged-apps +31,Packaging,Use single-project MSIX,Simplified packaging for single app,Single-project MSIX packaging,Separate WAP project when not needed,"true in csproj","Separate Windows Application Packaging project for simple apps",Low,https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/single-project-msix +32,Accessibility,Set AutomationProperties,Enable Narrator and screen reader support,AutomationProperties.Name on all interactive controls,Controls without accessible names,""," without name",High,https://learn.microsoft.com/en-us/windows/apps/design/accessibility/basic-accessibility-information +33,Accessibility,Support keyboard navigation,Full keyboard accessibility,Tab navigation and access keys for all controls,Mouse-only interactions,"","Window.PreviewKeyDown=""OnKeyDown"" with switch over args.Key",High,https://learn.microsoft.com/en-us/windows/apps/develop/input/keyboard-accelerators +57,Styling,Organize resources with merged dictionaries,Share styles and brushes via App.xaml MergedDictionaries instead of duplicating per page,MergedDictionaries in App.xaml for shared styles brushes and colors,Duplicating SolidColorBrush definitions on every page,"",SolidColorBrush Color hardcoded inline on every page,Medium,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/xaml-resource-dictionary +58,Architecture,Use AsyncRelayCommand for async commands,AsyncRelayCommand exposes IsRunning and supports cancellation for IO bound work,[RelayCommand] on async Task method or AsyncRelayCommand for IO work,async void event handlers or fire-and-forget Task.Run from button click,"[RelayCommand] private async Task LoadAsync(CancellationToken ct) { Items = await _service.FetchAsync(ct); }","private async void Button_Click(object s, RoutedEventArgs e) { await LoadAsync(); }",Medium,https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/asyncrelaycommand +59,Architecture,Use ILogger for structured logging,Microsoft.Extensions.Logging ILogger with DI for structured leveled logs,ILogger injected via constructor for diagnostic logging,Debug.WriteLine or Console.WriteLine for app diagnostics,"public MainViewModel(ILogger logger) { _logger = logger; } _logger.LogInformation(""Loaded {Count} items"", count);","Debug.WriteLine($""Loaded {count} items"");",Medium,https://learn.microsoft.com/en-us/dotnet/core/extensions/logging/overview diff --git a/cli/assets/data/stacks/wpf.csv b/cli/assets/data/stacks/wpf.csv new file mode 100644 index 0000000..d58e3e5 --- /dev/null +++ b/cli/assets/data/stacks/wpf.csv @@ -0,0 +1,57 @@ +No,Category,Guideline,Description,Do,Don't,Code Good,Code Bad,Severity,Docs URL +1,XAML,Use XAML for declarative UI,Define layout and visuals in XAML not code-behind,XAML for structure and styling,Build UI trees in C# code-behind,"","Full ControlTemplate copy to change background color",High,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/xaml-styles#lightweight-styling +11,Styling,Use WinUI theme resources,Consistent Fluent Design colors and brushes,WinUI theme resource keys for colors,Hardcoded hex color values,"Background=""{ThemeResource CardBackgroundFillColorDefaultBrush}""","Background=""#FF2D2D30""",High,https://learn.microsoft.com/en-us/windows/apps/design/signature-experiences/color +12,Styling,Support light and dark themes,Respect user and system theme preference,ThemeResource for theme-adaptive values,Hardcoded colors that break in dark mode,"Foreground=""{ThemeResource TextFillColorPrimaryBrush}""","Foreground=""Black""",High,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/xaml-theme-resources +13,Styling,Use Fluent Design system,Acrylic Mica Reveal and rounded corners,Built-in Fluent materials and effects,Custom blur and shadow implementations,"","Custom CompositionBrush recreating acrylic",Medium,https://learn.microsoft.com/en-us/windows/apps/design/signature-experiences/materials +14,Navigation,Use Frame for page navigation,Microsoft.UI.Xaml.Controls.Frame for WinUI 3 page navigation,Frame.Navigate with page types and parameters,Swapping UserControls in a ContentControl,"rootFrame.Navigate(typeof(SettingsPage), parameter);","contentArea.Content = new SettingsControl();",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/ui/navigation/navigate-between-two-pages +15,Navigation,Pass typed navigation parameters,Type-safe data passing between pages,Typed parameter in OnNavigatedTo,Dictionary or string parsing for parameters,"protected override void OnNavigatedTo(NavigationEventArgs e) { var item = (Item)e.Parameter; }","var id = int.Parse(e.Parameter.ToString());",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/ui/navigation/navigate-between-two-pages +16,Navigation,Handle back navigation,WinUI 3 uses NavigationView.BackRequested instead of UWP SystemNavigationManager,Register NavigationView.BackRequested handler and manage back stack,"Ignoring back navigation","navigationView.BackRequested += OnBackRequested;","No back button support",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/ui/navigation/navigation-history-and-backwards-navigation +17,Navigation,Use deep linking,Handle protocol activation so URIs route to the right page,Register protocol then check ExtendedActivationKind.Protocol on activation,Single entry point ignoring activation context,"AppInstance.GetCurrent().GetActivatedEventArgs() with ExtendedActivationKind.Protocol","Ignoring activation arguments",Medium,https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/applifecycle/applifecycle-rich-activation +18,Data Binding,Use ObservableCollection for lists,Notifies UI of collection changes,ObservableCollection for bound ItemsSources,List for bound collections,"ObservableCollection Items { get; } = new();","List Items { get; set; } = new();",High,https://learn.microsoft.com/en-us/windows/apps/develop/data-binding/data-binding-in-depth +19,Data Binding,Use INotifyPropertyChanged,Enable property change notification for UI updates,INotifyPropertyChanged on ViewModels,Properties without notification,"public string Name { get => _name; set => SetProperty(ref _name, value); }","public string Name { get; set; } without notification",High,https://learn.microsoft.com/en-us/windows/apps/develop/data-binding/data-binding-in-depth +20,Data Binding,Use function binding with x:Bind,Call methods directly in bindings,x:Bind with method references for transforms,IValueConverter for simple logic,"","IValueConverter class for bool to visibility",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/data-binding/function-bindings +21,Data Binding,Specify Mode explicitly on x:Bind,x:Bind defaults to OneTime not OneWay,Mode=OneWay or Mode=TwoWay when updates needed,Forgetting Mode and getting stale UI,"Text=""{x:Bind Title, Mode=OneWay}""","Text=""{x:Bind Title}"" expecting live updates",High,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/x-bind-markup-extension +22,Performance,Use ItemsRepeater for custom lists,Virtualizing layout with full control,ItemsRepeater for custom list layouts,ListView for highly customized item layouts,"","ListView with heavily modified template and removed chrome",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/ui/controls/items-repeater +23,Performance,Use incremental loading,Load data on demand as user scrolls,ISupportIncrementalLoading for large data sets,Loading entire dataset upfront,"class IncrementalItemSource : ObservableCollection, ISupportIncrementalLoading","await LoadAllItems() on page load for 10K items",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/data-binding/data-binding-in-depth +24,Performance,Reduce visual tree complexity,Simpler trees render faster,Minimal nesting in DataTemplates,Deeply nested panels in item templates,"","... 8 levels deep",Medium,https://learn.microsoft.com/en-us/windows/apps/develop/performance/optimize-xaml-loading +25,Performance,Use compiled bindings over reflection,x:Bind generates code at compile time,x:Bind for hot paths and list items,{Binding} in DataTemplates and frequently updated UI,"","",High,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/x-bind-markup-extension +26,Threading,Use DispatcherQueue not Dispatcher,WinUI 3 uses Microsoft.UI.Dispatching.DispatcherQueue instead of UWP CoreDispatcher,DispatcherQueue.TryEnqueue for UI thread access,Dispatcher.RunAsync (UWP pattern),"_dispatcherQueue.TryEnqueue(() => Status = ""Done"");","Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => ...);",High,https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.dispatching.dispatcherqueue +27,Threading,Use async/await for IO operations,Keep UI responsive during file and network access,async/await for IO so the UI thread keeps rendering,Synchronous IO on UI thread,"var data = await httpClient.GetStringAsync(url);","var data = httpClient.GetStringAsync(url).Result;",High,https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/ +28,Threading,Use Task.Run for CPU-bound work,Offload compute to thread pool,Task.Run for heavy computation,Long-running CPU work on UI thread,"var result = await Task.Run(() => ProcessLargeDataSet());","var result = ProcessLargeDataSet(); blocking UI",High,https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-based-asynchronous-programming +29,Packaging,Use WinAppSDK correctly,Windows App SDK provides the runtime,WinAppSDK NuGet package and WindowsAppSDK bootstrapper,Mixing UWP and WinUI 3 APIs,"","Using Windows.UI.Xaml instead of Microsoft.UI.Xaml",High,https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/ +30,Packaging,Use unpackaged or packaged appropriately,Choose deployment model for your scenario,Packaged (MSIX) for Store distribution,Unpackaged without considering API limitations,"None for unpackaged","Assuming all APIs work in unpackaged mode",Medium,https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/deploy-packaged-apps +31,Packaging,Use single-project MSIX,Simplified packaging for single app,Single-project MSIX packaging,Separate WAP project when not needed,"true in csproj","Separate Windows Application Packaging project for simple apps",Low,https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/single-project-msix +32,Accessibility,Set AutomationProperties,Enable Narrator and screen reader support,AutomationProperties.Name on all interactive controls,Controls without accessible names,""," without name",High,https://learn.microsoft.com/en-us/windows/apps/design/accessibility/basic-accessibility-information +33,Accessibility,Support keyboard navigation,Full keyboard accessibility,Tab navigation and access keys for all controls,Mouse-only interactions,"","Window.PreviewKeyDown=""OnKeyDown"" with switch over args.Key",High,https://learn.microsoft.com/en-us/windows/apps/develop/input/keyboard-accelerators +57,Styling,Organize resources with merged dictionaries,Share styles and brushes via App.xaml MergedDictionaries instead of duplicating per page,MergedDictionaries in App.xaml for shared styles brushes and colors,Duplicating SolidColorBrush definitions on every page,"",SolidColorBrush Color hardcoded inline on every page,Medium,https://learn.microsoft.com/en-us/windows/apps/develop/platform/xaml/xaml-resource-dictionary +58,Architecture,Use AsyncRelayCommand for async commands,AsyncRelayCommand exposes IsRunning and supports cancellation for IO bound work,[RelayCommand] on async Task method or AsyncRelayCommand for IO work,async void event handlers or fire-and-forget Task.Run from button click,"[RelayCommand] private async Task LoadAsync(CancellationToken ct) { Items = await _service.FetchAsync(ct); }","private async void Button_Click(object s, RoutedEventArgs e) { await LoadAsync(); }",Medium,https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/asyncrelaycommand +59,Architecture,Use ILogger for structured logging,Microsoft.Extensions.Logging ILogger with DI for structured leveled logs,ILogger injected via constructor for diagnostic logging,Debug.WriteLine or Console.WriteLine for app diagnostics,"public MainViewModel(ILogger logger) { _logger = logger; } _logger.LogInformation(""Loaded {Count} items"", count);","Debug.WriteLine($""Loaded {count} items"");",Medium,https://learn.microsoft.com/en-us/dotnet/core/extensions/logging/overview diff --git a/src/ui-ux-pro-max/data/stacks/wpf.csv b/src/ui-ux-pro-max/data/stacks/wpf.csv new file mode 100644 index 0000000..d58e3e5 --- /dev/null +++ b/src/ui-ux-pro-max/data/stacks/wpf.csv @@ -0,0 +1,57 @@ +No,Category,Guideline,Description,Do,Don't,Code Good,Code Bad,Severity,Docs URL +1,XAML,Use XAML for declarative UI,Define layout and visuals in XAML not code-behind,XAML for structure and styling,Build UI trees in C# code-behind,"